blob: d901d4bffeaa42faa1c2ea866653646828007171 [file] [log] [blame]
Eric Moore635374e2009-03-09 01:21:12 -06001/*
2 * Scsi Host Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c
Kashyap, Desai31b7f2e2010-03-17 16:28:04 +05305 * Copyright (C) 2007-2010 LSI Corporation
Eric Moore635374e2009-03-09 01:21:12 -06006 * (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41 * USA.
42 */
43
Eric Moore635374e2009-03-09 01:21:12 -060044#include <linux/module.h>
45#include <linux/kernel.h>
46#include <linux/init.h>
47#include <linux/errno.h>
48#include <linux/blkdev.h>
49#include <linux/sched.h>
50#include <linux/workqueue.h>
51#include <linux/delay.h>
52#include <linux/pci.h>
53#include <linux/interrupt.h>
Kashyap, Desaief7c80c2010-04-05 14:20:07 +053054#include <linux/aer.h>
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +053055#include <linux/raid_class.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090056#include <linux/slab.h>
Eric Moore635374e2009-03-09 01:21:12 -060057
58#include "mpt2sas_base.h"
59
60MODULE_AUTHOR(MPT2SAS_AUTHOR);
61MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION);
62MODULE_LICENSE("GPL");
63MODULE_VERSION(MPT2SAS_DRIVER_VERSION);
64
65#define RAID_CHANNEL 1
66
67/* forward proto's */
68static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
69 struct _sas_node *sas_expander);
70static void _firmware_event_work(struct work_struct *work);
71
Kashyap, Desaif3eedd62010-06-17 13:46:13 +053072static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid);
73
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +053074static void _scsih_scan_start(struct Scsi_Host *shost);
75static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
76
Eric Moore635374e2009-03-09 01:21:12 -060077/* global parameters */
Eric Mooreba33fad2009-03-15 21:37:18 -060078LIST_HEAD(mpt2sas_ioc_list);
Eric Moore635374e2009-03-09 01:21:12 -060079
80/* local parameters */
Eric Moore635374e2009-03-09 01:21:12 -060081static u8 scsi_io_cb_idx = -1;
82static u8 tm_cb_idx = -1;
83static u8 ctl_cb_idx = -1;
84static u8 base_cb_idx = -1;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +053085static u8 port_enable_cb_idx = -1;
Eric Moore635374e2009-03-09 01:21:12 -060086static u8 transport_cb_idx = -1;
Kashyap, Desai744090d2009-10-05 15:56:56 +053087static u8 scsih_cb_idx = -1;
Eric Moore635374e2009-03-09 01:21:12 -060088static u8 config_cb_idx = -1;
89static int mpt_ids;
90
Kashyap, Desai77e63ed2009-09-14 11:04:23 +053091static u8 tm_tr_cb_idx = -1 ;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +053092static u8 tm_tr_volume_cb_idx = -1 ;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +053093static u8 tm_sas_control_cb_idx = -1;
94
Eric Moore635374e2009-03-09 01:21:12 -060095/* command line options */
Eric Mooreba33fad2009-03-15 21:37:18 -060096static u32 logging_level;
Eric Moore635374e2009-03-09 01:21:12 -060097MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
98 "(default=0)");
99
Kashyap, Desaia3e1e552011-06-14 10:56:12 +0530100static ushort max_sectors = 0xFFFF;
101module_param(max_sectors, ushort, 0);
nagalakshmi.nandigama@lsi.com9ac49d32011-12-01 07:52:08 +0530102MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767");
Kashyap, Desaia3e1e552011-06-14 10:56:12 +0530103
Eric Moore635374e2009-03-09 01:21:12 -0600104/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
105#define MPT2SAS_MAX_LUN (16895)
106static int max_lun = MPT2SAS_MAX_LUN;
107module_param(max_lun, int, 0);
108MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
109
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +0530110/* diag_buffer_enable is bitwise
111 * bit 0 set = TRACE
112 * bit 1 set = SNAPSHOT
113 * bit 2 set = EXTENDED
114 *
115 * Either bit can be set, or both
116 */
117static int diag_buffer_enable = -1;
118module_param(diag_buffer_enable, int, 0);
119MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
120 "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
121
Eric Moore635374e2009-03-09 01:21:12 -0600122/**
123 * struct sense_info - common structure for obtaining sense keys
124 * @skey: sense key
125 * @asc: additional sense code
126 * @ascq: additional sense code qualifier
127 */
128struct sense_info {
129 u8 skey;
130 u8 asc;
131 u8 ascq;
132};
133
134
Kashyap, Desai3ace8e02011-05-04 16:35:58 +0530135#define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC)
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +0530136#define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD)
137#define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
Eric Moore635374e2009-03-09 01:21:12 -0600138/**
139 * struct fw_event_work - firmware event struct
140 * @list: link list framework
141 * @work: work object (ioc->fault_reset_work_q)
Kashyap, Desaif1c35e62010-03-09 16:31:43 +0530142 * @cancel_pending_work: flag set during reset handling
Eric Moore635374e2009-03-09 01:21:12 -0600143 * @ioc: per adapter object
Kashyap, Desai3ace8e02011-05-04 16:35:58 +0530144 * @device_handle: device handle
Eric Moore635374e2009-03-09 01:21:12 -0600145 * @VF_ID: virtual function id
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530146 * @VP_ID: virtual port id
Eric Moore635374e2009-03-09 01:21:12 -0600147 * @ignore: flag meaning this event has been marked to ignore
148 * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
149 * @event_data: reply event data payload follows
150 *
151 * This object stored on ioc->fw_event_list.
152 */
153struct fw_event_work {
154 struct list_head list;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +0530155 u8 cancel_pending_work;
156 struct delayed_work delayed_work;
Eric Moore635374e2009-03-09 01:21:12 -0600157 struct MPT2SAS_ADAPTER *ioc;
Kashyap, Desai3ace8e02011-05-04 16:35:58 +0530158 u16 device_handle;
Eric Moore635374e2009-03-09 01:21:12 -0600159 u8 VF_ID;
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530160 u8 VP_ID;
Eric Moore635374e2009-03-09 01:21:12 -0600161 u8 ignore;
162 u16 event;
163 void *event_data;
164};
165
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +0530166/* raid transport support */
167static struct raid_template *mpt2sas_raid_template;
168
Eric Moore635374e2009-03-09 01:21:12 -0600169/**
170 * struct _scsi_io_transfer - scsi io transfer
171 * @handle: sas device handle (assigned by firmware)
172 * @is_raid: flag set for hidden raid components
173 * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
174 * @data_length: data transfer length
175 * @data_dma: dma pointer to data
176 * @sense: sense data
177 * @lun: lun number
178 * @cdb_length: cdb length
179 * @cdb: cdb contents
Eric Moore635374e2009-03-09 01:21:12 -0600180 * @timeout: timeout for this command
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530181 * @VF_ID: virtual function id
182 * @VP_ID: virtual port id
183 * @valid_reply: flag set for reply message
Eric Moore635374e2009-03-09 01:21:12 -0600184 * @sense_length: sense length
185 * @ioc_status: ioc status
186 * @scsi_state: scsi state
187 * @scsi_status: scsi staus
188 * @log_info: log information
189 * @transfer_length: data length transfer when there is a reply message
190 *
191 * Used for sending internal scsi commands to devices within this module.
192 * Refer to _scsi_send_scsi_io().
193 */
194struct _scsi_io_transfer {
195 u16 handle;
196 u8 is_raid;
197 enum dma_data_direction dir;
198 u32 data_length;
199 dma_addr_t data_dma;
200 u8 sense[SCSI_SENSE_BUFFERSIZE];
201 u32 lun;
202 u8 cdb_length;
203 u8 cdb[32];
204 u8 timeout;
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530205 u8 VF_ID;
206 u8 VP_ID;
Eric Moore635374e2009-03-09 01:21:12 -0600207 u8 valid_reply;
208 /* the following bits are only valid when 'valid_reply = 1' */
209 u32 sense_length;
210 u16 ioc_status;
211 u8 scsi_state;
212 u8 scsi_status;
213 u32 log_info;
214 u32 transfer_length;
215};
216
217/*
218 * The pci device ids are defined in mpi/mpi2_cnfg.h.
219 */
220static struct pci_device_id scsih_pci_table[] = {
221 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
222 PCI_ANY_ID, PCI_ANY_ID },
223 /* Falcon ~ 2008*/
224 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
225 PCI_ANY_ID, PCI_ANY_ID },
226 /* Liberator ~ 2108 */
227 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
228 PCI_ANY_ID, PCI_ANY_ID },
229 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
230 PCI_ANY_ID, PCI_ANY_ID },
231 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
232 PCI_ANY_ID, PCI_ANY_ID },
Kashyap, Desaidb271362009-09-23 17:24:27 +0530233 /* Meteor ~ 2116 */
Eric Moore635374e2009-03-09 01:21:12 -0600234 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
235 PCI_ANY_ID, PCI_ANY_ID },
236 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
237 PCI_ANY_ID, PCI_ANY_ID },
Kashyap, Desaidb271362009-09-23 17:24:27 +0530238 /* Thunderbolt ~ 2208 */
239 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
240 PCI_ANY_ID, PCI_ANY_ID },
241 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
242 PCI_ANY_ID, PCI_ANY_ID },
243 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
244 PCI_ANY_ID, PCI_ANY_ID },
245 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
246 PCI_ANY_ID, PCI_ANY_ID },
247 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
248 PCI_ANY_ID, PCI_ANY_ID },
249 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
250 PCI_ANY_ID, PCI_ANY_ID },
Kashyap, Desai203d65b2010-06-17 13:37:59 +0530251 /* Mustang ~ 2308 */
252 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
Kashyap, Desaidb271362009-09-23 17:24:27 +0530253 PCI_ANY_ID, PCI_ANY_ID },
Kashyap, Desai203d65b2010-06-17 13:37:59 +0530254 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
255 PCI_ANY_ID, PCI_ANY_ID },
256 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
Kashyap, Desaidb271362009-09-23 17:24:27 +0530257 PCI_ANY_ID, PCI_ANY_ID },
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530258 /* SSS6200 */
259 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
260 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore635374e2009-03-09 01:21:12 -0600261 {0} /* Terminating entry */
262};
263MODULE_DEVICE_TABLE(pci, scsih_pci_table);
264
265/**
Eric Moored5d135b2009-05-18 13:02:08 -0600266 * _scsih_set_debug_level - global setting of ioc->logging_level.
Eric Moore635374e2009-03-09 01:21:12 -0600267 *
268 * Note: The logging levels are defined in mpt2sas_debug.h.
269 */
270static int
Eric Moored5d135b2009-05-18 13:02:08 -0600271_scsih_set_debug_level(const char *val, struct kernel_param *kp)
Eric Moore635374e2009-03-09 01:21:12 -0600272{
273 int ret = param_set_int(val, kp);
274 struct MPT2SAS_ADAPTER *ioc;
275
276 if (ret)
277 return ret;
278
279 printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level);
Eric Mooreba33fad2009-03-15 21:37:18 -0600280 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
Eric Moore635374e2009-03-09 01:21:12 -0600281 ioc->logging_level = logging_level;
282 return 0;
283}
Eric Moored5d135b2009-05-18 13:02:08 -0600284module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
Eric Moore635374e2009-03-09 01:21:12 -0600285 &logging_level, 0644);
286
287/**
288 * _scsih_srch_boot_sas_address - search based on sas_address
289 * @sas_address: sas address
290 * @boot_device: boot device object from bios page 2
291 *
292 * Returns 1 when there's a match, 0 means no match.
293 */
294static inline int
295_scsih_srch_boot_sas_address(u64 sas_address,
296 Mpi2BootDeviceSasWwid_t *boot_device)
297{
298 return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
299}
300
301/**
302 * _scsih_srch_boot_device_name - search based on device name
303 * @device_name: device name specified in INDENTIFY fram
304 * @boot_device: boot device object from bios page 2
305 *
306 * Returns 1 when there's a match, 0 means no match.
307 */
308static inline int
309_scsih_srch_boot_device_name(u64 device_name,
310 Mpi2BootDeviceDeviceName_t *boot_device)
311{
312 return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
313}
314
315/**
316 * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
317 * @enclosure_logical_id: enclosure logical id
318 * @slot_number: slot number
319 * @boot_device: boot device object from bios page 2
320 *
321 * Returns 1 when there's a match, 0 means no match.
322 */
323static inline int
324_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
325 Mpi2BootDeviceEnclosureSlot_t *boot_device)
326{
327 return (enclosure_logical_id == le64_to_cpu(boot_device->
328 EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
329 SlotNumber)) ? 1 : 0;
330}
331
332/**
333 * _scsih_is_boot_device - search for matching boot device.
334 * @sas_address: sas address
335 * @device_name: device name specified in INDENTIFY fram
336 * @enclosure_logical_id: enclosure logical id
337 * @slot_number: slot number
338 * @form: specifies boot device form
339 * @boot_device: boot device object from bios page 2
340 *
341 * Returns 1 when there's a match, 0 means no match.
342 */
343static int
344_scsih_is_boot_device(u64 sas_address, u64 device_name,
345 u64 enclosure_logical_id, u16 slot, u8 form,
346 Mpi2BiosPage2BootDevice_t *boot_device)
347{
348 int rc = 0;
349
350 switch (form) {
351 case MPI2_BIOSPAGE2_FORM_SAS_WWID:
352 if (!sas_address)
353 break;
354 rc = _scsih_srch_boot_sas_address(
355 sas_address, &boot_device->SasWwid);
356 break;
357 case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
358 if (!enclosure_logical_id)
359 break;
360 rc = _scsih_srch_boot_encl_slot(
361 enclosure_logical_id,
362 slot, &boot_device->EnclosureSlot);
363 break;
364 case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
365 if (!device_name)
366 break;
367 rc = _scsih_srch_boot_device_name(
368 device_name, &boot_device->DeviceName);
369 break;
370 case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
371 break;
372 }
373
374 return rc;
375}
376
377/**
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530378 * _scsih_get_sas_address - set the sas_address for given device handle
379 * @handle: device handle
380 * @sas_address: sas address
381 *
382 * Returns 0 success, non-zero when failure
383 */
384static int
385_scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle,
386 u64 *sas_address)
387{
388 Mpi2SasDevicePage0_t sas_device_pg0;
389 Mpi2ConfigReply_t mpi_reply;
390 u32 ioc_status;
nagalakshmi.nandigama@lsi.com24f09b52011-10-19 15:36:47 +0530391 *sas_address = 0;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530392
393 if (handle <= ioc->sas_hba.num_phys) {
394 *sas_address = ioc->sas_hba.sas_address;
395 return 0;
nagalakshmi.nandigama@lsi.com24f09b52011-10-19 15:36:47 +0530396 }
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530397
398 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
399 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
nagalakshmi.nandigama@lsi.com24f09b52011-10-19 15:36:47 +0530400 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
401 __FILE__, __LINE__, __func__);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530402 return -ENXIO;
403 }
404
nagalakshmi.nandigama@lsi.com24f09b52011-10-19 15:36:47 +0530405 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
406 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
407 *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
408 return 0;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530409 }
410
nagalakshmi.nandigama@lsi.com24f09b52011-10-19 15:36:47 +0530411 /* we hit this becuase the given parent handle doesn't exist */
412 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
413 return -ENXIO;
414 /* else error case */
415 printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), "
416 "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
417 __FILE__, __LINE__, __func__);
418 return -EIO;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530419}
420
421/**
Eric Moore635374e2009-03-09 01:21:12 -0600422 * _scsih_determine_boot_device - determine boot device.
423 * @ioc: per adapter object
424 * @device: either sas_device or raid_device object
425 * @is_raid: [flag] 1 = raid object, 0 = sas object
426 *
427 * Determines whether this device should be first reported device to
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300428 * to scsi-ml or sas transport, this purpose is for persistent boot device.
Eric Moore635374e2009-03-09 01:21:12 -0600429 * There are primary, alternate, and current entries in bios page 2. The order
430 * priority is primary, alternate, then current. This routine saves
431 * the corresponding device object and is_raid flag in the ioc object.
432 * The saved data to be used later in _scsih_probe_boot_devices().
433 */
434static void
435_scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
436 void *device, u8 is_raid)
437{
438 struct _sas_device *sas_device;
439 struct _raid_device *raid_device;
440 u64 sas_address;
441 u64 device_name;
442 u64 enclosure_logical_id;
443 u16 slot;
444
445 /* only process this function when driver loads */
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +0530446 if (!ioc->is_driver_loading)
447 return;
448
449 /* no Bios, return immediately */
450 if (!ioc->bios_pg3.BiosVersion)
Eric Moore635374e2009-03-09 01:21:12 -0600451 return;
452
453 if (!is_raid) {
454 sas_device = device;
455 sas_address = sas_device->sas_address;
456 device_name = sas_device->device_name;
457 enclosure_logical_id = sas_device->enclosure_logical_id;
458 slot = sas_device->slot;
459 } else {
460 raid_device = device;
461 sas_address = raid_device->wwid;
462 device_name = 0;
463 enclosure_logical_id = 0;
464 slot = 0;
465 }
466
467 if (!ioc->req_boot_device.device) {
468 if (_scsih_is_boot_device(sas_address, device_name,
469 enclosure_logical_id, slot,
470 (ioc->bios_pg2.ReqBootDeviceForm &
471 MPI2_BIOSPAGE2_FORM_MASK),
472 &ioc->bios_pg2.RequestedBootDevice)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530473 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -0600474 "%s: req_boot_device(0x%016llx)\n",
475 ioc->name, __func__,
476 (unsigned long long)sas_address));
477 ioc->req_boot_device.device = device;
478 ioc->req_boot_device.is_raid = is_raid;
479 }
480 }
481
482 if (!ioc->req_alt_boot_device.device) {
483 if (_scsih_is_boot_device(sas_address, device_name,
484 enclosure_logical_id, slot,
485 (ioc->bios_pg2.ReqAltBootDeviceForm &
486 MPI2_BIOSPAGE2_FORM_MASK),
487 &ioc->bios_pg2.RequestedAltBootDevice)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530488 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -0600489 "%s: req_alt_boot_device(0x%016llx)\n",
490 ioc->name, __func__,
491 (unsigned long long)sas_address));
492 ioc->req_alt_boot_device.device = device;
493 ioc->req_alt_boot_device.is_raid = is_raid;
494 }
495 }
496
497 if (!ioc->current_boot_device.device) {
498 if (_scsih_is_boot_device(sas_address, device_name,
499 enclosure_logical_id, slot,
500 (ioc->bios_pg2.CurrentBootDeviceForm &
501 MPI2_BIOSPAGE2_FORM_MASK),
502 &ioc->bios_pg2.CurrentBootDevice)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530503 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -0600504 "%s: current_boot_device(0x%016llx)\n",
505 ioc->name, __func__,
506 (unsigned long long)sas_address));
507 ioc->current_boot_device.device = device;
508 ioc->current_boot_device.is_raid = is_raid;
509 }
510 }
511}
512
513/**
514 * mpt2sas_scsih_sas_device_find_by_sas_address - sas device search
515 * @ioc: per adapter object
516 * @sas_address: sas address
517 * Context: Calling function should acquire ioc->sas_device_lock
518 *
519 * This searches for sas_device based on sas_address, then return sas_device
520 * object.
521 */
522struct _sas_device *
523mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
524 u64 sas_address)
525{
Kashyap, Desaicd9843f2010-03-09 16:32:17 +0530526 struct _sas_device *sas_device;
Eric Moore635374e2009-03-09 01:21:12 -0600527
Kashyap, Desaicd9843f2010-03-09 16:32:17 +0530528 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
529 if (sas_device->sas_address == sas_address)
530 return sas_device;
Eric Moore635374e2009-03-09 01:21:12 -0600531
Kashyap, Desaicd9843f2010-03-09 16:32:17 +0530532 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
533 if (sas_device->sas_address == sas_address)
534 return sas_device;
535
536 return NULL;
Eric Moore635374e2009-03-09 01:21:12 -0600537}
538
539/**
540 * _scsih_sas_device_find_by_handle - sas device search
541 * @ioc: per adapter object
542 * @handle: sas device handle (assigned by firmware)
543 * Context: Calling function should acquire ioc->sas_device_lock
544 *
545 * This searches for sas_device based on sas_address, then return sas_device
546 * object.
547 */
548static struct _sas_device *
549_scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
550{
Kashyap, Desaicd9843f2010-03-09 16:32:17 +0530551 struct _sas_device *sas_device;
Eric Moore635374e2009-03-09 01:21:12 -0600552
Kashyap, Desaicd9843f2010-03-09 16:32:17 +0530553 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
554 if (sas_device->handle == handle)
555 return sas_device;
Eric Moore635374e2009-03-09 01:21:12 -0600556
Kashyap, Desaicd9843f2010-03-09 16:32:17 +0530557 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
558 if (sas_device->handle == handle)
559 return sas_device;
560
561 return NULL;
Eric Moore635374e2009-03-09 01:21:12 -0600562}
563
564/**
565 * _scsih_sas_device_remove - remove sas_device from list.
566 * @ioc: per adapter object
567 * @sas_device: the sas_device object
568 * Context: This function will acquire ioc->sas_device_lock.
569 *
570 * Removing object and freeing associated memory from the ioc->sas_device_list.
571 */
572static void
573_scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
574 struct _sas_device *sas_device)
575{
576 unsigned long flags;
577
Kashyap, Desai980ead32010-04-08 17:55:22 +0530578 if (!sas_device)
579 return;
580
Eric Moore635374e2009-03-09 01:21:12 -0600581 spin_lock_irqsave(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +0530582 list_del(&sas_device->list);
583 kfree(sas_device);
Eric Moore635374e2009-03-09 01:21:12 -0600584 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
585}
586
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +0530587
Eric Moore635374e2009-03-09 01:21:12 -0600588/**
589 * _scsih_sas_device_add - insert sas_device to the list.
590 * @ioc: per adapter object
591 * @sas_device: the sas_device object
592 * Context: This function will acquire ioc->sas_device_lock.
593 *
594 * Adding new object to the ioc->sas_device_list.
595 */
596static void
597_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
598 struct _sas_device *sas_device)
599{
600 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -0600601
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530602 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
Eric Moore635374e2009-03-09 01:21:12 -0600603 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
604 sas_device->handle, (unsigned long long)sas_device->sas_address));
605
606 spin_lock_irqsave(&ioc->sas_device_lock, flags);
607 list_add_tail(&sas_device->list, &ioc->sas_device_list);
608 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
609
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530610 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
nagalakshmi.nandigama@lsi.com35116db2011-10-21 10:08:07 +0530611 sas_device->sas_address_parent)) {
Eric Moore635374e2009-03-09 01:21:12 -0600612 _scsih_sas_device_remove(ioc, sas_device);
nagalakshmi.nandigama@lsi.com23edb6e2011-12-01 07:43:50 +0530613 } else if (!sas_device->starget) {
614 /* When asyn scanning is enabled, its not possible to remove
615 * devices while scanning is turned on due to an oops in
616 * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
617 */
618 if (!ioc->is_driver_loading)
619 mpt2sas_transport_port_remove(ioc,
620 sas_device->sas_address,
621 sas_device->sas_address_parent);
622 _scsih_sas_device_remove(ioc, sas_device);
623 }
Eric Moore635374e2009-03-09 01:21:12 -0600624}
625
626/**
627 * _scsih_sas_device_init_add - insert sas_device to the list.
628 * @ioc: per adapter object
629 * @sas_device: the sas_device object
630 * Context: This function will acquire ioc->sas_device_lock.
631 *
632 * Adding new object at driver load time to the ioc->sas_device_init_list.
633 */
634static void
635_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
636 struct _sas_device *sas_device)
637{
638 unsigned long flags;
639
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530640 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
Eric Moore635374e2009-03-09 01:21:12 -0600641 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
642 sas_device->handle, (unsigned long long)sas_device->sas_address));
643
644 spin_lock_irqsave(&ioc->sas_device_lock, flags);
645 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
Eric Moore635374e2009-03-09 01:21:12 -0600646 _scsih_determine_boot_device(ioc, sas_device, 0);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +0530647 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -0600648}
649
650/**
Eric Moore635374e2009-03-09 01:21:12 -0600651 * _scsih_raid_device_find_by_id - raid device search
652 * @ioc: per adapter object
653 * @id: sas device target id
654 * @channel: sas device channel
655 * Context: Calling function should acquire ioc->raid_device_lock
656 *
657 * This searches for raid_device based on target id, then return raid_device
658 * object.
659 */
660static struct _raid_device *
661_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel)
662{
663 struct _raid_device *raid_device, *r;
664
665 r = NULL;
666 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
667 if (raid_device->id == id && raid_device->channel == channel) {
668 r = raid_device;
669 goto out;
670 }
671 }
672
673 out:
674 return r;
675}
676
677/**
678 * _scsih_raid_device_find_by_handle - raid device search
679 * @ioc: per adapter object
680 * @handle: sas device handle (assigned by firmware)
681 * Context: Calling function should acquire ioc->raid_device_lock
682 *
683 * This searches for raid_device based on handle, then return raid_device
684 * object.
685 */
686static struct _raid_device *
687_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
688{
689 struct _raid_device *raid_device, *r;
690
691 r = NULL;
692 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
693 if (raid_device->handle != handle)
694 continue;
695 r = raid_device;
696 goto out;
697 }
698
699 out:
700 return r;
701}
702
703/**
704 * _scsih_raid_device_find_by_wwid - raid device search
705 * @ioc: per adapter object
706 * @handle: sas device handle (assigned by firmware)
707 * Context: Calling function should acquire ioc->raid_device_lock
708 *
709 * This searches for raid_device based on wwid, then return raid_device
710 * object.
711 */
712static struct _raid_device *
713_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid)
714{
715 struct _raid_device *raid_device, *r;
716
717 r = NULL;
718 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
719 if (raid_device->wwid != wwid)
720 continue;
721 r = raid_device;
722 goto out;
723 }
724
725 out:
726 return r;
727}
728
729/**
730 * _scsih_raid_device_add - add raid_device object
731 * @ioc: per adapter object
732 * @raid_device: raid_device object
733 *
734 * This is added to the raid_device_list link list.
735 */
736static void
737_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
738 struct _raid_device *raid_device)
739{
740 unsigned long flags;
741
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530742 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
Eric Moore635374e2009-03-09 01:21:12 -0600743 "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
744 raid_device->handle, (unsigned long long)raid_device->wwid));
745
746 spin_lock_irqsave(&ioc->raid_device_lock, flags);
747 list_add_tail(&raid_device->list, &ioc->raid_device_list);
748 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
749}
750
751/**
752 * _scsih_raid_device_remove - delete raid_device object
753 * @ioc: per adapter object
754 * @raid_device: raid_device object
755 *
Eric Moore635374e2009-03-09 01:21:12 -0600756 */
757static void
758_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
759 struct _raid_device *raid_device)
760{
761 unsigned long flags;
762
763 spin_lock_irqsave(&ioc->raid_device_lock, flags);
764 list_del(&raid_device->list);
Eric Moore635374e2009-03-09 01:21:12 -0600765 kfree(raid_device);
766 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
767}
768
769/**
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530770 * mpt2sas_scsih_expander_find_by_handle - expander device search
771 * @ioc: per adapter object
772 * @handle: expander handle (assigned by firmware)
773 * Context: Calling function should acquire ioc->sas_device_lock
774 *
775 * This searches for expander device based on handle, then returns the
776 * sas_node object.
777 */
778struct _sas_node *
779mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
780{
781 struct _sas_node *sas_expander, *r;
782
783 r = NULL;
784 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
785 if (sas_expander->handle != handle)
786 continue;
787 r = sas_expander;
788 goto out;
789 }
790 out:
791 return r;
792}
793
794/**
Eric Moore635374e2009-03-09 01:21:12 -0600795 * mpt2sas_scsih_expander_find_by_sas_address - expander device search
796 * @ioc: per adapter object
797 * @sas_address: sas address
798 * Context: Calling function should acquire ioc->sas_node_lock.
799 *
800 * This searches for expander device based on sas_address, then returns the
801 * sas_node object.
802 */
803struct _sas_node *
804mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
805 u64 sas_address)
806{
807 struct _sas_node *sas_expander, *r;
808
809 r = NULL;
810 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
811 if (sas_expander->sas_address != sas_address)
812 continue;
813 r = sas_expander;
814 goto out;
815 }
816 out:
817 return r;
818}
819
820/**
821 * _scsih_expander_node_add - insert expander device to the list.
822 * @ioc: per adapter object
823 * @sas_expander: the sas_device object
824 * Context: This function will acquire ioc->sas_node_lock.
825 *
826 * Adding new object to the ioc->sas_expander_list.
827 *
828 * Return nothing.
829 */
830static void
831_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc,
832 struct _sas_node *sas_expander)
833{
834 unsigned long flags;
835
836 spin_lock_irqsave(&ioc->sas_node_lock, flags);
837 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
838 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
839}
840
841/**
842 * _scsih_is_end_device - determines if device is an end device
843 * @device_info: bitfield providing information about the device.
844 * Context: none
845 *
846 * Returns 1 if end device.
847 */
848static int
849_scsih_is_end_device(u32 device_info)
850{
851 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
852 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
853 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
854 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
855 return 1;
856 else
857 return 0;
858}
859
860/**
Kashyap, Desaiec07a052011-01-05 17:54:32 +0530861 * _scsih_scsi_lookup_get - returns scmd entry
Eric Moore635374e2009-03-09 01:21:12 -0600862 * @ioc: per adapter object
863 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -0600864 *
865 * Returns the smid stored scmd pointer.
866 */
867static struct scsi_cmnd *
868_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
869{
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530870 return ioc->scsi_lookup[smid - 1].scmd;
Eric Moore635374e2009-03-09 01:21:12 -0600871}
872
873/**
Kashyap, Desaiec07a052011-01-05 17:54:32 +0530874 * _scsih_scsi_lookup_get_clear - returns scmd entry
875 * @ioc: per adapter object
876 * @smid: system request message index
877 *
878 * Returns the smid stored scmd pointer.
879 * Then will derefrence the stored scmd pointer.
880 */
881static inline struct scsi_cmnd *
882_scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
883{
884 unsigned long flags;
885 struct scsi_cmnd *scmd;
886
887 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
888 scmd = ioc->scsi_lookup[smid - 1].scmd;
889 ioc->scsi_lookup[smid - 1].scmd = NULL;
890 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
891
892 return scmd;
893}
894
895/**
Eric Moore635374e2009-03-09 01:21:12 -0600896 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
897 * @ioc: per adapter object
898 * @smid: system request message index
899 * @scmd: pointer to scsi command object
900 * Context: This function will acquire ioc->scsi_lookup_lock.
901 *
902 * This will search for a scmd pointer in the scsi_lookup array,
903 * returning the revelent smid. A returned value of zero means invalid.
904 */
905static u16
906_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
907 *scmd)
908{
909 u16 smid;
910 unsigned long flags;
911 int i;
912
913 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
914 smid = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530915 for (i = 0; i < ioc->scsiio_depth; i++) {
Eric Moore635374e2009-03-09 01:21:12 -0600916 if (ioc->scsi_lookup[i].scmd == scmd) {
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530917 smid = ioc->scsi_lookup[i].smid;
Eric Moore635374e2009-03-09 01:21:12 -0600918 goto out;
919 }
920 }
921 out:
922 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
923 return smid;
924}
925
926/**
927 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
928 * @ioc: per adapter object
929 * @id: target id
930 * @channel: channel
931 * Context: This function will acquire ioc->scsi_lookup_lock.
932 *
933 * This will search for a matching channel:id in the scsi_lookup array,
934 * returning 1 if found.
935 */
936static u8
937_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
938 int channel)
939{
940 u8 found;
941 unsigned long flags;
942 int i;
943
944 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
945 found = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530946 for (i = 0 ; i < ioc->scsiio_depth; i++) {
Eric Moore635374e2009-03-09 01:21:12 -0600947 if (ioc->scsi_lookup[i].scmd &&
948 (ioc->scsi_lookup[i].scmd->device->id == id &&
949 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
950 found = 1;
951 goto out;
952 }
953 }
954 out:
955 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
956 return found;
957}
958
959/**
Eric Moore993e0da2009-05-18 13:00:45 -0600960 * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
961 * @ioc: per adapter object
962 * @id: target id
963 * @lun: lun number
964 * @channel: channel
965 * Context: This function will acquire ioc->scsi_lookup_lock.
966 *
967 * This will search for a matching channel:id:lun in the scsi_lookup array,
968 * returning 1 if found.
969 */
970static u8
971_scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
972 unsigned int lun, int channel)
973{
974 u8 found;
975 unsigned long flags;
976 int i;
977
978 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
979 found = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530980 for (i = 0 ; i < ioc->scsiio_depth; i++) {
Eric Moore993e0da2009-05-18 13:00:45 -0600981 if (ioc->scsi_lookup[i].scmd &&
982 (ioc->scsi_lookup[i].scmd->device->id == id &&
983 ioc->scsi_lookup[i].scmd->device->channel == channel &&
984 ioc->scsi_lookup[i].scmd->device->lun == lun)) {
985 found = 1;
986 goto out;
987 }
988 }
989 out:
990 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
991 return found;
992}
993
994/**
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530995 * _scsih_get_chain_buffer_tracker - obtain chain tracker
Eric Moore635374e2009-03-09 01:21:12 -0600996 * @ioc: per adapter object
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530997 * @smid: smid associated to an IO request
Eric Moore635374e2009-03-09 01:21:12 -0600998 *
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530999 * Returns chain tracker(from ioc->free_chain_list)
Eric Moore635374e2009-03-09 01:21:12 -06001000 */
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301001static struct chain_tracker *
1002_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
Eric Moore635374e2009-03-09 01:21:12 -06001003{
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301004 struct chain_tracker *chain_req;
1005 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06001006
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301007 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1008 if (list_empty(&ioc->free_chain_list)) {
1009 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
nagalakshmi.nandigama@lsi.comaff132d2011-12-01 07:53:08 +05301010 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not "
1011 "available\n", ioc->name));
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301012 return NULL;
1013 }
1014 chain_req = list_entry(ioc->free_chain_list.next,
1015 struct chain_tracker, tracker_list);
1016 list_del_init(&chain_req->tracker_list);
1017 list_add_tail(&chain_req->tracker_list,
1018 &ioc->scsi_lookup[smid - 1].chain_list);
1019 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1020 return chain_req;
Eric Moore635374e2009-03-09 01:21:12 -06001021}
1022
1023/**
1024 * _scsih_build_scatter_gather - main sg creation routine
1025 * @ioc: per adapter object
1026 * @scmd: scsi command
1027 * @smid: system request message index
1028 * Context: none.
1029 *
1030 * The main routine that builds scatter gather table from a given
1031 * scsi request sent via the .queuecommand main handler.
1032 *
1033 * Returns 0 success, anything else error
1034 */
1035static int
1036_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
1037 struct scsi_cmnd *scmd, u16 smid)
1038{
1039 Mpi2SCSIIORequest_t *mpi_request;
1040 dma_addr_t chain_dma;
1041 struct scatterlist *sg_scmd;
1042 void *sg_local, *chain;
1043 u32 chain_offset;
1044 u32 chain_length;
1045 u32 chain_flags;
FUJITA Tomonoribb789d02010-03-09 11:09:50 +09001046 int sges_left;
Eric Moore635374e2009-03-09 01:21:12 -06001047 u32 sges_in_segment;
1048 u32 sgl_flags;
1049 u32 sgl_flags_last_element;
1050 u32 sgl_flags_end_buffer;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301051 struct chain_tracker *chain_req;
Eric Moore635374e2009-03-09 01:21:12 -06001052
1053 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1054
1055 /* init scatter gather flags */
1056 sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
1057 if (scmd->sc_data_direction == DMA_TO_DEVICE)
1058 sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
1059 sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
1060 << MPI2_SGE_FLAGS_SHIFT;
1061 sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
1062 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
1063 << MPI2_SGE_FLAGS_SHIFT;
1064 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1065
1066 sg_scmd = scsi_sglist(scmd);
1067 sges_left = scsi_dma_map(scmd);
FUJITA Tomonoribb789d02010-03-09 11:09:50 +09001068 if (sges_left < 0) {
Eric Moore635374e2009-03-09 01:21:12 -06001069 sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
1070 " failed: request for %d bytes!\n", scsi_bufflen(scmd));
1071 return -ENOMEM;
1072 }
1073
1074 sg_local = &mpi_request->SGL;
1075 sges_in_segment = ioc->max_sges_in_main_message;
1076 if (sges_left <= sges_in_segment)
1077 goto fill_in_last_segment;
1078
1079 mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
1080 (sges_in_segment * ioc->sge_size))/4;
1081
1082 /* fill in main message segment when there is a chain following */
1083 while (sges_in_segment) {
1084 if (sges_in_segment == 1)
1085 ioc->base_add_sg_single(sg_local,
1086 sgl_flags_last_element | sg_dma_len(sg_scmd),
1087 sg_dma_address(sg_scmd));
1088 else
1089 ioc->base_add_sg_single(sg_local, sgl_flags |
1090 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1091 sg_scmd = sg_next(sg_scmd);
1092 sg_local += ioc->sge_size;
1093 sges_left--;
1094 sges_in_segment--;
1095 }
1096
1097 /* initializing the chain flags and pointers */
1098 chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301099 chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
1100 if (!chain_req)
1101 return -1;
1102 chain = chain_req->chain_buffer;
1103 chain_dma = chain_req->chain_buffer_dma;
Eric Moore635374e2009-03-09 01:21:12 -06001104 do {
1105 sges_in_segment = (sges_left <=
1106 ioc->max_sges_in_chain_message) ? sges_left :
1107 ioc->max_sges_in_chain_message;
1108 chain_offset = (sges_left == sges_in_segment) ?
1109 0 : (sges_in_segment * ioc->sge_size)/4;
1110 chain_length = sges_in_segment * ioc->sge_size;
1111 if (chain_offset) {
1112 chain_offset = chain_offset <<
1113 MPI2_SGE_CHAIN_OFFSET_SHIFT;
1114 chain_length += ioc->sge_size;
1115 }
1116 ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
1117 chain_length, chain_dma);
1118 sg_local = chain;
1119 if (!chain_offset)
1120 goto fill_in_last_segment;
1121
1122 /* fill in chain segments */
1123 while (sges_in_segment) {
1124 if (sges_in_segment == 1)
1125 ioc->base_add_sg_single(sg_local,
1126 sgl_flags_last_element |
1127 sg_dma_len(sg_scmd),
1128 sg_dma_address(sg_scmd));
1129 else
1130 ioc->base_add_sg_single(sg_local, sgl_flags |
1131 sg_dma_len(sg_scmd),
1132 sg_dma_address(sg_scmd));
1133 sg_scmd = sg_next(sg_scmd);
1134 sg_local += ioc->sge_size;
1135 sges_left--;
1136 sges_in_segment--;
1137 }
1138
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301139 chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
1140 if (!chain_req)
1141 return -1;
1142 chain = chain_req->chain_buffer;
1143 chain_dma = chain_req->chain_buffer_dma;
Eric Moore635374e2009-03-09 01:21:12 -06001144 } while (1);
1145
1146
1147 fill_in_last_segment:
1148
1149 /* fill the last segment */
1150 while (sges_left) {
1151 if (sges_left == 1)
1152 ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
1153 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1154 else
1155 ioc->base_add_sg_single(sg_local, sgl_flags |
1156 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1157 sg_scmd = sg_next(sg_scmd);
1158 sg_local += ioc->sge_size;
1159 sges_left--;
1160 }
1161
1162 return 0;
1163}
1164
1165/**
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301166 * _scsih_adjust_queue_depth - setting device queue depth
Eric Moore635374e2009-03-09 01:21:12 -06001167 * @sdev: scsi device struct
1168 * @qdepth: requested queue depth
1169 *
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301170 *
1171 * Returns nothing
Eric Moore635374e2009-03-09 01:21:12 -06001172 */
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301173static void
1174_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
Eric Moore635374e2009-03-09 01:21:12 -06001175{
1176 struct Scsi_Host *shost = sdev->host;
1177 int max_depth;
Kashyap, Desaie0077d62009-09-23 17:30:22 +05301178 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1179 struct MPT2SAS_DEVICE *sas_device_priv_data;
1180 struct MPT2SAS_TARGET *sas_target_priv_data;
1181 struct _sas_device *sas_device;
1182 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06001183
1184 max_depth = shost->can_queue;
Kashyap, Desaie0077d62009-09-23 17:30:22 +05301185
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;
1195 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1196 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1197 sas_device_priv_data->sas_target->sas_address);
Kashyap, Desaie0077d62009-09-23 17:30:22 +05301198 if (sas_device && sas_device->device_info &
1199 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1200 max_depth = MPT2SAS_SATA_QUEUE_DEPTH;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301201 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desaie0077d62009-09-23 17:30:22 +05301202
1203 not_sata:
1204
Eric Moore635374e2009-03-09 01:21:12 -06001205 if (!sdev->tagged_supported)
1206 max_depth = 1;
1207 if (qdepth > max_depth)
1208 qdepth = max_depth;
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301209 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
1210}
1211
1212/**
1213 * _scsih_change_queue_depth - setting device queue depth
1214 * @sdev: scsi device struct
1215 * @qdepth: requested queue depth
1216 * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
1217 * (see include/scsi/scsi_host.h for definition)
1218 *
1219 * Returns queue depth.
1220 */
1221static int
1222_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1223{
1224 if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
1225 _scsih_adjust_queue_depth(sdev, qdepth);
1226 else if (reason == SCSI_QDEPTH_QFULL)
1227 scsi_track_queue_full(sdev, qdepth);
1228 else
1229 return -EOPNOTSUPP;
Eric Moore635374e2009-03-09 01:21:12 -06001230
1231 if (sdev->inquiry_len > 7)
1232 sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
1233 "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
1234 sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
1235 sdev->ordered_tags, sdev->scsi_level,
1236 (sdev->inquiry[7] & 2) >> 1);
1237
1238 return sdev->queue_depth;
1239}
1240
1241/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301242 * _scsih_change_queue_type - changing device queue tag type
Eric Moore635374e2009-03-09 01:21:12 -06001243 * @sdev: scsi device struct
1244 * @tag_type: requested tag type
1245 *
1246 * Returns queue tag type.
1247 */
1248static int
Eric Moored5d135b2009-05-18 13:02:08 -06001249_scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
Eric Moore635374e2009-03-09 01:21:12 -06001250{
1251 if (sdev->tagged_supported) {
1252 scsi_set_tag_type(sdev, tag_type);
1253 if (tag_type)
1254 scsi_activate_tcq(sdev, sdev->queue_depth);
1255 else
1256 scsi_deactivate_tcq(sdev, sdev->queue_depth);
1257 } else
1258 tag_type = 0;
1259
1260 return tag_type;
1261}
1262
1263/**
Eric Moored5d135b2009-05-18 13:02:08 -06001264 * _scsih_target_alloc - target add routine
Eric Moore635374e2009-03-09 01:21:12 -06001265 * @starget: scsi target struct
1266 *
1267 * Returns 0 if ok. Any other return is assumed to be an error and
1268 * the device is ignored.
1269 */
1270static int
Eric Moored5d135b2009-05-18 13:02:08 -06001271_scsih_target_alloc(struct scsi_target *starget)
Eric Moore635374e2009-03-09 01:21:12 -06001272{
1273 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1274 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1275 struct MPT2SAS_TARGET *sas_target_priv_data;
1276 struct _sas_device *sas_device;
1277 struct _raid_device *raid_device;
1278 unsigned long flags;
1279 struct sas_rphy *rphy;
1280
1281 sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
1282 if (!sas_target_priv_data)
1283 return -ENOMEM;
1284
1285 starget->hostdata = sas_target_priv_data;
1286 sas_target_priv_data->starget = starget;
1287 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
1288
1289 /* RAID volumes */
1290 if (starget->channel == RAID_CHANNEL) {
1291 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1292 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1293 starget->channel);
1294 if (raid_device) {
1295 sas_target_priv_data->handle = raid_device->handle;
1296 sas_target_priv_data->sas_address = raid_device->wwid;
1297 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301298 if (ioc->is_warpdrive)
1299 sas_target_priv_data->raid_device = raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06001300 raid_device->starget = starget;
1301 }
1302 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1303 return 0;
1304 }
1305
1306 /* sas/sata devices */
1307 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1308 rphy = dev_to_rphy(starget->dev.parent);
1309 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1310 rphy->identify.sas_address);
1311
1312 if (sas_device) {
1313 sas_target_priv_data->handle = sas_device->handle;
1314 sas_target_priv_data->sas_address = sas_device->sas_address;
1315 sas_device->starget = starget;
1316 sas_device->id = starget->id;
1317 sas_device->channel = starget->channel;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05301318 if (test_bit(sas_device->handle, ioc->pd_handles))
Eric Moore635374e2009-03-09 01:21:12 -06001319 sas_target_priv_data->flags |=
1320 MPT_TARGET_FLAGS_RAID_COMPONENT;
1321 }
1322 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1323
1324 return 0;
1325}
1326
1327/**
Eric Moored5d135b2009-05-18 13:02:08 -06001328 * _scsih_target_destroy - target destroy routine
Eric Moore635374e2009-03-09 01:21:12 -06001329 * @starget: scsi target struct
1330 *
1331 * Returns nothing.
1332 */
1333static void
Eric Moored5d135b2009-05-18 13:02:08 -06001334_scsih_target_destroy(struct scsi_target *starget)
Eric Moore635374e2009-03-09 01:21:12 -06001335{
1336 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1337 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1338 struct MPT2SAS_TARGET *sas_target_priv_data;
1339 struct _sas_device *sas_device;
1340 struct _raid_device *raid_device;
1341 unsigned long flags;
1342 struct sas_rphy *rphy;
1343
1344 sas_target_priv_data = starget->hostdata;
1345 if (!sas_target_priv_data)
1346 return;
1347
1348 if (starget->channel == RAID_CHANNEL) {
1349 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1350 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1351 starget->channel);
1352 if (raid_device) {
1353 raid_device->starget = NULL;
1354 raid_device->sdev = NULL;
1355 }
1356 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1357 goto out;
1358 }
1359
1360 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1361 rphy = dev_to_rphy(starget->dev.parent);
1362 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1363 rphy->identify.sas_address);
Eric Moore8901cbb2009-04-21 15:41:32 -06001364 if (sas_device && (sas_device->starget == starget) &&
1365 (sas_device->id == starget->id) &&
1366 (sas_device->channel == starget->channel))
Eric Moore635374e2009-03-09 01:21:12 -06001367 sas_device->starget = NULL;
1368
1369 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1370
1371 out:
1372 kfree(sas_target_priv_data);
1373 starget->hostdata = NULL;
1374}
1375
1376/**
Eric Moored5d135b2009-05-18 13:02:08 -06001377 * _scsih_slave_alloc - device add routine
Eric Moore635374e2009-03-09 01:21:12 -06001378 * @sdev: scsi device struct
1379 *
1380 * Returns 0 if ok. Any other return is assumed to be an error and
1381 * the device is ignored.
1382 */
1383static int
Eric Moored5d135b2009-05-18 13:02:08 -06001384_scsih_slave_alloc(struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001385{
1386 struct Scsi_Host *shost;
1387 struct MPT2SAS_ADAPTER *ioc;
1388 struct MPT2SAS_TARGET *sas_target_priv_data;
1389 struct MPT2SAS_DEVICE *sas_device_priv_data;
1390 struct scsi_target *starget;
1391 struct _raid_device *raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06001392 unsigned long flags;
1393
1394 sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
1395 if (!sas_device_priv_data)
1396 return -ENOMEM;
1397
1398 sas_device_priv_data->lun = sdev->lun;
1399 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1400
1401 starget = scsi_target(sdev);
1402 sas_target_priv_data = starget->hostdata;
1403 sas_target_priv_data->num_luns++;
1404 sas_device_priv_data->sas_target = sas_target_priv_data;
1405 sdev->hostdata = sas_device_priv_data;
1406 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1407 sdev->no_uld_attach = 1;
1408
1409 shost = dev_to_shost(&starget->dev);
1410 ioc = shost_priv(shost);
1411 if (starget->channel == RAID_CHANNEL) {
1412 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1413 raid_device = _scsih_raid_device_find_by_id(ioc,
1414 starget->id, starget->channel);
1415 if (raid_device)
1416 raid_device->sdev = sdev; /* raid is single lun */
1417 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06001418 }
1419
Eric Moore635374e2009-03-09 01:21:12 -06001420 return 0;
1421}
1422
1423/**
Eric Moored5d135b2009-05-18 13:02:08 -06001424 * _scsih_slave_destroy - device destroy routine
Eric Moore635374e2009-03-09 01:21:12 -06001425 * @sdev: scsi device struct
1426 *
1427 * Returns nothing.
1428 */
1429static void
Eric Moored5d135b2009-05-18 13:02:08 -06001430_scsih_slave_destroy(struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001431{
1432 struct MPT2SAS_TARGET *sas_target_priv_data;
1433 struct scsi_target *starget;
nagalakshmi.nandigama@lsi.com35116db2011-10-21 10:08:07 +05301434 struct Scsi_Host *shost;
1435 struct MPT2SAS_ADAPTER *ioc;
1436 struct _sas_device *sas_device;
1437 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06001438
1439 if (!sdev->hostdata)
1440 return;
1441
1442 starget = scsi_target(sdev);
1443 sas_target_priv_data = starget->hostdata;
1444 sas_target_priv_data->num_luns--;
nagalakshmi.nandigama@lsi.com35116db2011-10-21 10:08:07 +05301445
1446 shost = dev_to_shost(&starget->dev);
1447 ioc = shost_priv(shost);
1448
1449 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1450 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1451 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1452 sas_target_priv_data->sas_address);
nagalakshmi.nandigama@lsi.com23edb6e2011-12-01 07:43:50 +05301453 if (sas_device && !sas_target_priv_data->num_luns)
nagalakshmi.nandigama@lsi.com35116db2011-10-21 10:08:07 +05301454 sas_device->starget = NULL;
1455 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1456 }
1457
Eric Moore635374e2009-03-09 01:21:12 -06001458 kfree(sdev->hostdata);
1459 sdev->hostdata = NULL;
1460}
1461
1462/**
Eric Moored5d135b2009-05-18 13:02:08 -06001463 * _scsih_display_sata_capabilities - sata capabilities
Eric Moore635374e2009-03-09 01:21:12 -06001464 * @ioc: per adapter object
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301465 * @handle: device handle
Eric Moore635374e2009-03-09 01:21:12 -06001466 * @sdev: scsi device struct
1467 */
1468static void
Eric Moored5d135b2009-05-18 13:02:08 -06001469_scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301470 u16 handle, struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001471{
1472 Mpi2ConfigReply_t mpi_reply;
1473 Mpi2SasDevicePage0_t sas_device_pg0;
1474 u32 ioc_status;
1475 u16 flags;
1476 u32 device_info;
1477
1478 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301479 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
Eric Moore635374e2009-03-09 01:21:12 -06001480 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1481 ioc->name, __FILE__, __LINE__, __func__);
1482 return;
1483 }
1484
1485 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1486 MPI2_IOCSTATUS_MASK;
1487 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1488 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1489 ioc->name, __FILE__, __LINE__, __func__);
1490 return;
1491 }
1492
1493 flags = le16_to_cpu(sas_device_pg0.Flags);
Kashyap, Desaie94f6742010-03-17 16:24:52 +05301494 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
Eric Moore635374e2009-03-09 01:21:12 -06001495
1496 sdev_printk(KERN_INFO, sdev,
1497 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1498 "sw_preserve(%s)\n",
1499 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1500 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1501 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1502 "n",
1503 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1504 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1505 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1506}
1507
1508/**
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301509 * _scsih_is_raid - return boolean indicating device is raid volume
1510 * @dev the device struct object
1511 */
1512static int
1513_scsih_is_raid(struct device *dev)
1514{
1515 struct scsi_device *sdev = to_scsi_device(dev);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301516 struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301517
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301518 if (ioc->is_warpdrive)
1519 return 0;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301520 return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
1521}
1522
1523/**
1524 * _scsih_get_resync - get raid volume resync percent complete
1525 * @dev the device struct object
1526 */
1527static void
1528_scsih_get_resync(struct device *dev)
1529{
1530 struct scsi_device *sdev = to_scsi_device(dev);
1531 struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
1532 static struct _raid_device *raid_device;
1533 unsigned long flags;
1534 Mpi2RaidVolPage0_t vol_pg0;
1535 Mpi2ConfigReply_t mpi_reply;
1536 u32 volume_status_flags;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301537 u8 percent_complete;
1538 u16 handle;
1539
1540 percent_complete = 0;
1541 handle = 0;
1542 if (ioc->is_warpdrive)
1543 goto out;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301544
1545 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1546 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1547 sdev->channel);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301548 if (raid_device) {
1549 handle = raid_device->handle;
1550 percent_complete = raid_device->percent_complete;
1551 }
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301552 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1553
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301554 if (!handle)
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301555 goto out;
1556
1557 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301558 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301559 sizeof(Mpi2RaidVolPage0_t))) {
1560 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1561 ioc->name, __FILE__, __LINE__, __func__);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301562 percent_complete = 0;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301563 goto out;
1564 }
1565
1566 volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301567 if (!(volume_status_flags &
1568 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
1569 percent_complete = 0;
1570
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301571 out:
1572 raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
1573}
1574
1575/**
1576 * _scsih_get_state - get raid volume level
1577 * @dev the device struct object
1578 */
1579static void
1580_scsih_get_state(struct device *dev)
1581{
1582 struct scsi_device *sdev = to_scsi_device(dev);
1583 struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
1584 static struct _raid_device *raid_device;
1585 unsigned long flags;
1586 Mpi2RaidVolPage0_t vol_pg0;
1587 Mpi2ConfigReply_t mpi_reply;
1588 u32 volstate;
1589 enum raid_state state = RAID_STATE_UNKNOWN;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301590 u16 handle = 0;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301591
1592 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1593 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1594 sdev->channel);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301595 if (raid_device)
1596 handle = raid_device->handle;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301597 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1598
1599 if (!raid_device)
1600 goto out;
1601
1602 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301603 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301604 sizeof(Mpi2RaidVolPage0_t))) {
1605 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1606 ioc->name, __FILE__, __LINE__, __func__);
1607 goto out;
1608 }
1609
1610 volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1611 if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
1612 state = RAID_STATE_RESYNCING;
1613 goto out;
1614 }
1615
1616 switch (vol_pg0.VolumeState) {
1617 case MPI2_RAID_VOL_STATE_OPTIMAL:
1618 case MPI2_RAID_VOL_STATE_ONLINE:
1619 state = RAID_STATE_ACTIVE;
1620 break;
1621 case MPI2_RAID_VOL_STATE_DEGRADED:
1622 state = RAID_STATE_DEGRADED;
1623 break;
1624 case MPI2_RAID_VOL_STATE_FAILED:
1625 case MPI2_RAID_VOL_STATE_MISSING:
1626 state = RAID_STATE_OFFLINE;
1627 break;
1628 }
1629 out:
1630 raid_set_state(mpt2sas_raid_template, dev, state);
1631}
1632
1633/**
1634 * _scsih_set_level - set raid level
1635 * @sdev: scsi device struct
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301636 * @volume_type: volume type
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301637 */
1638static void
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301639_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301640{
1641 enum raid_level level = RAID_LEVEL_UNKNOWN;
1642
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301643 switch (volume_type) {
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301644 case MPI2_RAID_VOL_TYPE_RAID0:
1645 level = RAID_LEVEL_0;
1646 break;
1647 case MPI2_RAID_VOL_TYPE_RAID10:
1648 level = RAID_LEVEL_10;
1649 break;
1650 case MPI2_RAID_VOL_TYPE_RAID1E:
1651 level = RAID_LEVEL_1E;
1652 break;
1653 case MPI2_RAID_VOL_TYPE_RAID1:
1654 level = RAID_LEVEL_1;
1655 break;
1656 }
1657
1658 raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level);
1659}
1660
1661/**
Eric Moore635374e2009-03-09 01:21:12 -06001662 * _scsih_get_volume_capabilities - volume capabilities
1663 * @ioc: per adapter object
1664 * @sas_device: the raid_device object
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301665 *
1666 * Returns 0 for success, else 1
Eric Moore635374e2009-03-09 01:21:12 -06001667 */
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301668static int
Eric Moore635374e2009-03-09 01:21:12 -06001669_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
1670 struct _raid_device *raid_device)
1671{
1672 Mpi2RaidVolPage0_t *vol_pg0;
1673 Mpi2RaidPhysDiskPage0_t pd_pg0;
1674 Mpi2SasDevicePage0_t sas_device_pg0;
1675 Mpi2ConfigReply_t mpi_reply;
1676 u16 sz;
1677 u8 num_pds;
1678
1679 if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
1680 &num_pds)) || !num_pds) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301681 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1682 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1683 __func__));
1684 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001685 }
1686
1687 raid_device->num_pds = num_pds;
1688 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1689 sizeof(Mpi2RaidVol0PhysDisk_t));
1690 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1691 if (!vol_pg0) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301692 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1693 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1694 __func__));
1695 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001696 }
1697
1698 if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1699 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301700 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1701 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1702 __func__));
Eric Moore635374e2009-03-09 01:21:12 -06001703 kfree(vol_pg0);
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301704 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001705 }
1706
1707 raid_device->volume_type = vol_pg0->VolumeType;
1708
1709 /* figure out what the underlying devices are by
1710 * obtaining the device_info bits for the 1st device
1711 */
1712 if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1713 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1714 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1715 if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1716 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1717 le16_to_cpu(pd_pg0.DevHandle)))) {
1718 raid_device->device_info =
1719 le32_to_cpu(sas_device_pg0.DeviceInfo);
1720 }
1721 }
1722
1723 kfree(vol_pg0);
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301724 return 0;
Eric Moore635374e2009-03-09 01:21:12 -06001725}
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301726/**
1727 * _scsih_disable_ddio - Disable direct I/O for all the volumes
1728 * @ioc: per adapter object
1729 */
1730static void
1731_scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
1732{
1733 Mpi2RaidVolPage1_t vol_pg1;
1734 Mpi2ConfigReply_t mpi_reply;
1735 struct _raid_device *raid_device;
1736 u16 handle;
1737 u16 ioc_status;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301738 unsigned long flags;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301739
1740 handle = 0xFFFF;
1741 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1742 &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1743 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1744 MPI2_IOCSTATUS_MASK;
1745 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
1746 break;
1747 handle = le16_to_cpu(vol_pg1.DevHandle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301748 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301749 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
1750 if (raid_device)
1751 raid_device->direct_io_enabled = 0;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301752 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301753 }
1754 return;
1755}
1756
1757
1758/**
1759 * _scsih_get_num_volumes - Get number of volumes in the ioc
1760 * @ioc: per adapter object
1761 */
1762static u8
1763_scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc)
1764{
1765 Mpi2RaidVolPage1_t vol_pg1;
1766 Mpi2ConfigReply_t mpi_reply;
1767 u16 handle;
1768 u8 vol_cnt = 0;
1769 u16 ioc_status;
1770
1771 handle = 0xFFFF;
1772 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1773 &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1774 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1775 MPI2_IOCSTATUS_MASK;
1776 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
1777 break;
1778 vol_cnt++;
1779 handle = le16_to_cpu(vol_pg1.DevHandle);
1780 }
1781 return vol_cnt;
1782}
1783
1784
1785/**
1786 * _scsih_init_warpdrive_properties - Set properties for warpdrive direct I/O.
1787 * @ioc: per adapter object
1788 * @raid_device: the raid_device object
1789 */
1790static void
1791_scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
1792 struct _raid_device *raid_device)
1793{
1794 Mpi2RaidVolPage0_t *vol_pg0;
1795 Mpi2RaidPhysDiskPage0_t pd_pg0;
1796 Mpi2ConfigReply_t mpi_reply;
1797 u16 sz;
1798 u8 num_pds, count;
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301799 unsigned long stripe_sz, block_sz;
1800 u8 stripe_exp, block_exp;
1801 u64 dev_max_lba;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301802
1803 if (!ioc->is_warpdrive)
1804 return;
1805
1806 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) {
1807 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1808 "globally as drives are exposed\n", ioc->name);
1809 return;
1810 }
1811 if (_scsih_get_num_volumes(ioc) > 1) {
1812 _scsih_disable_ddio(ioc);
1813 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1814 "globally as number of drives > 1\n", ioc->name);
1815 return;
1816 }
1817 if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
1818 &num_pds)) || !num_pds) {
1819 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1820 "Failure in computing number of drives\n", ioc->name);
1821 return;
1822 }
1823
1824 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1825 sizeof(Mpi2RaidVol0PhysDisk_t));
1826 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1827 if (!vol_pg0) {
1828 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1829 "Memory allocation failure for RVPG0\n", ioc->name);
1830 return;
1831 }
1832
1833 if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1834 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1835 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1836 "Failure in retrieving RVPG0\n", ioc->name);
1837 kfree(vol_pg0);
1838 return;
1839 }
1840
1841 /*
1842 * WARPDRIVE:If number of physical disks in a volume exceeds the max pds
1843 * assumed for WARPDRIVE, disable direct I/O
1844 */
1845 if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
1846 printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled "
1847 "for the drive with handle(0x%04x): num_mem=%d, "
1848 "max_mem_allowed=%d\n", ioc->name, raid_device->handle,
1849 num_pds, MPT_MAX_WARPDRIVE_PDS);
1850 kfree(vol_pg0);
1851 return;
1852 }
1853 for (count = 0; count < num_pds; count++) {
1854 if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1855 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1856 vol_pg0->PhysDisk[count].PhysDiskNum) ||
nagalakshmi.nandigama@lsi.comd838c362012-03-20 12:07:48 +05301857 le16_to_cpu(pd_pg0.DevHandle) ==
1858 MPT2SAS_INVALID_DEVICE_HANDLE) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301859 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
1860 "disabled for the drive with handle(0x%04x) member"
1861 "handle retrieval failed for member number=%d\n",
1862 ioc->name, raid_device->handle,
1863 vol_pg0->PhysDisk[count].PhysDiskNum);
1864 goto out_error;
1865 }
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301866 /* Disable direct I/O if member drive lba exceeds 4 bytes */
1867 dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA);
1868 if (dev_max_lba >> 32) {
1869 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
1870 "disabled for the drive with handle(0x%04x) member"
1871 "handle (0x%04x) unsupported max lba 0x%016llx\n",
1872 ioc->name, raid_device->handle,
1873 le16_to_cpu(pd_pg0.DevHandle),
1874 (unsigned long long)dev_max_lba);
1875 goto out_error;
1876 }
1877
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301878 raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
1879 }
1880
1881 /*
1882 * Assumption for WD: Direct I/O is not supported if the volume is
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301883 * not RAID0
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301884 */
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301885 if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301886 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1887 "for the drive with handle(0x%04x): type=%d, "
1888 "s_sz=%uK, blk_size=%u\n", ioc->name,
1889 raid_device->handle, raid_device->volume_type,
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301890 (le32_to_cpu(vol_pg0->StripeSize) *
1891 le16_to_cpu(vol_pg0->BlockSize)) / 1024,
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301892 le16_to_cpu(vol_pg0->BlockSize));
1893 goto out_error;
1894 }
1895
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301896 stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301897 stripe_exp = find_first_bit(&stripe_sz, 32);
1898 if (stripe_exp == 32) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301899 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301900 "for the drive with handle(0x%04x) invalid stripe sz %uK\n",
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301901 ioc->name, raid_device->handle,
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301902 (le32_to_cpu(vol_pg0->StripeSize) *
1903 le16_to_cpu(vol_pg0->BlockSize)) / 1024);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301904 goto out_error;
1905 }
1906 raid_device->stripe_exponent = stripe_exp;
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05301907 block_sz = le16_to_cpu(vol_pg0->BlockSize);
1908 block_exp = find_first_bit(&block_sz, 16);
1909 if (block_exp == 16) {
1910 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1911 "for the drive with handle(0x%04x) invalid block sz %u\n",
1912 ioc->name, raid_device->handle,
1913 le16_to_cpu(vol_pg0->BlockSize));
1914 goto out_error;
1915 }
1916 raid_device->block_exponent = block_exp;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301917 raid_device->direct_io_enabled = 1;
1918
1919 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive"
1920 " with handle(0x%04x)\n", ioc->name, raid_device->handle);
1921 /*
1922 * WARPDRIVE: Though the following fields are not used for direct IO,
1923 * stored for future purpose:
1924 */
1925 raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
1926 raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
1927 raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
1928
1929
1930 kfree(vol_pg0);
1931 return;
1932
1933out_error:
1934 raid_device->direct_io_enabled = 0;
1935 for (count = 0; count < num_pds; count++)
1936 raid_device->pd_handle[count] = 0;
1937 kfree(vol_pg0);
1938 return;
1939}
Eric Moore635374e2009-03-09 01:21:12 -06001940
1941/**
Kashyap, Desai84f0b042009-12-16 18:56:28 +05301942 * _scsih_enable_tlr - setting TLR flags
1943 * @ioc: per adapter object
1944 * @sdev: scsi device struct
1945 *
1946 * Enabling Transaction Layer Retries for tape devices when
1947 * vpd page 0x90 is present
1948 *
1949 */
1950static void
1951_scsih_enable_tlr(struct MPT2SAS_ADAPTER *ioc, struct scsi_device *sdev)
1952{
1953 /* only for TAPE */
1954 if (sdev->type != TYPE_TAPE)
1955 return;
1956
1957 if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
1958 return;
1959
1960 sas_enable_tlr(sdev);
1961 sdev_printk(KERN_INFO, sdev, "TLR %s\n",
1962 sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
1963 return;
1964
1965}
1966
1967/**
Eric Moored5d135b2009-05-18 13:02:08 -06001968 * _scsih_slave_configure - device configure routine.
Eric Moore635374e2009-03-09 01:21:12 -06001969 * @sdev: scsi device struct
1970 *
1971 * Returns 0 if ok. Any other return is assumed to be an error and
1972 * the device is ignored.
1973 */
1974static int
Eric Moored5d135b2009-05-18 13:02:08 -06001975_scsih_slave_configure(struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001976{
1977 struct Scsi_Host *shost = sdev->host;
1978 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1979 struct MPT2SAS_DEVICE *sas_device_priv_data;
1980 struct MPT2SAS_TARGET *sas_target_priv_data;
1981 struct _sas_device *sas_device;
1982 struct _raid_device *raid_device;
1983 unsigned long flags;
1984 int qdepth;
1985 u8 ssp_target = 0;
1986 char *ds = "";
1987 char *r_level = "";
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301988 u16 handle, volume_handle = 0;
1989 u64 volume_wwid = 0;
Eric Moore635374e2009-03-09 01:21:12 -06001990
1991 qdepth = 1;
1992 sas_device_priv_data = sdev->hostdata;
1993 sas_device_priv_data->configured_lun = 1;
1994 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1995 sas_target_priv_data = sas_device_priv_data->sas_target;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05301996 handle = sas_target_priv_data->handle;
Eric Moore635374e2009-03-09 01:21:12 -06001997
1998 /* raid volume handling */
1999 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
2000
2001 spin_lock_irqsave(&ioc->raid_device_lock, flags);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05302002 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06002003 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
2004 if (!raid_device) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302005 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2006 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
2007 __LINE__, __func__));
2008 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002009 }
2010
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302011 if (_scsih_get_volume_capabilities(ioc, raid_device)) {
2012 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2013 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
2014 __LINE__, __func__));
2015 return 1;
2016 }
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302017 /*
2018 * WARPDRIVE: Initialize the required data for Direct IO
2019 */
2020 _scsih_init_warpdrive_properties(ioc, raid_device);
2021
Eric Moore635374e2009-03-09 01:21:12 -06002022 /* RAID Queue Depth Support
2023 * IS volume = underlying qdepth of drive type, either
2024 * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
2025 * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH)
2026 */
2027 if (raid_device->device_info &
2028 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
2029 qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
2030 ds = "SSP";
2031 } else {
2032 qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
2033 if (raid_device->device_info &
2034 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
2035 ds = "SATA";
2036 else
2037 ds = "STP";
2038 }
2039
2040 switch (raid_device->volume_type) {
2041 case MPI2_RAID_VOL_TYPE_RAID0:
2042 r_level = "RAID0";
2043 break;
2044 case MPI2_RAID_VOL_TYPE_RAID1E:
2045 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
Kashyap, Desaied79f122009-08-20 13:23:49 +05302046 if (ioc->manu_pg10.OEMIdentifier &&
Kashyap, Desaic97951e2011-06-14 10:54:56 +05302047 (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
Kashyap, Desaied79f122009-08-20 13:23:49 +05302048 MFG10_GF0_R10_DISPLAY) &&
2049 !(raid_device->num_pds % 2))
2050 r_level = "RAID10";
2051 else
2052 r_level = "RAID1E";
Eric Moore635374e2009-03-09 01:21:12 -06002053 break;
2054 case MPI2_RAID_VOL_TYPE_RAID1:
2055 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
2056 r_level = "RAID1";
2057 break;
2058 case MPI2_RAID_VOL_TYPE_RAID10:
2059 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
2060 r_level = "RAID10";
2061 break;
2062 case MPI2_RAID_VOL_TYPE_UNKNOWN:
2063 default:
2064 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
2065 r_level = "RAIDX";
2066 break;
2067 }
2068
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302069 if (!ioc->hide_ir_msg)
2070 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
2071 "wwid(0x%016llx), pd_count(%d), type(%s)\n",
2072 r_level, raid_device->handle,
2073 (unsigned long long)raid_device->wwid,
2074 raid_device->num_pds, ds);
Mike Christiee881a172009-10-15 17:46:39 -07002075 _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05302076 /* raid transport support */
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302077 if (!ioc->is_warpdrive)
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05302078 _scsih_set_level(sdev, raid_device->volume_type);
Eric Moore635374e2009-03-09 01:21:12 -06002079 return 0;
2080 }
2081
2082 /* non-raid handling */
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05302083 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2084 if (mpt2sas_config_get_volume_handle(ioc, handle,
2085 &volume_handle)) {
2086 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2087 "failure at %s:%d/%s()!\n", ioc->name,
2088 __FILE__, __LINE__, __func__));
2089 return 1;
2090 }
2091 if (volume_handle && mpt2sas_config_get_volume_wwid(ioc,
2092 volume_handle, &volume_wwid)) {
2093 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2094 "failure at %s:%d/%s()!\n", ioc->name,
2095 __FILE__, __LINE__, __func__));
2096 return 1;
2097 }
2098 }
2099
Eric Moore635374e2009-03-09 01:21:12 -06002100 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2101 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
2102 sas_device_priv_data->sas_target->sas_address);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05302103 if (!sas_device) {
2104 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302105 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05302106 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
2107 __LINE__, __func__));
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302108 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002109 }
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05302110 sas_device->volume_handle = volume_handle;
2111 sas_device->volume_wwid = volume_wwid;
2112 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
2113 qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
2114 ssp_target = 1;
2115 ds = "SSP";
2116 } else {
2117 qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
2118 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
2119 ds = "STP";
2120 else if (sas_device->device_info &
2121 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
2122 ds = "SATA";
2123 }
2124 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
2125 "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
2126 ds, sas_device->handle,
2127 (unsigned long long)sas_device->sas_address,
2128 sas_device->phy,
2129 (unsigned long long)sas_device->device_name);
2130 sdev_printk(KERN_INFO, sdev, "%s: "
2131 "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
2132 (unsigned long long) sas_device->enclosure_logical_id,
2133 sas_device->slot);
2134
2135 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2136 if (!ssp_target)
2137 _scsih_display_sata_capabilities(ioc, handle, sdev);
2138
Eric Moore635374e2009-03-09 01:21:12 -06002139
Mike Christiee881a172009-10-15 17:46:39 -07002140 _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
Eric Moore635374e2009-03-09 01:21:12 -06002141
Kashyap, Desai84f0b042009-12-16 18:56:28 +05302142 if (ssp_target) {
Eric Moore635374e2009-03-09 01:21:12 -06002143 sas_read_port_mode_page(sdev);
Kashyap, Desai84f0b042009-12-16 18:56:28 +05302144 _scsih_enable_tlr(ioc, sdev);
2145 }
Eric Moore635374e2009-03-09 01:21:12 -06002146 return 0;
2147}
2148
2149/**
Eric Moored5d135b2009-05-18 13:02:08 -06002150 * _scsih_bios_param - fetch head, sector, cylinder info for a disk
Eric Moore635374e2009-03-09 01:21:12 -06002151 * @sdev: scsi device struct
2152 * @bdev: pointer to block device context
2153 * @capacity: device size (in 512 byte sectors)
2154 * @params: three element array to place output:
2155 * params[0] number of heads (max 255)
2156 * params[1] number of sectors (max 63)
2157 * params[2] number of cylinders
2158 *
2159 * Return nothing.
2160 */
2161static int
Eric Moored5d135b2009-05-18 13:02:08 -06002162_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
Eric Moore635374e2009-03-09 01:21:12 -06002163 sector_t capacity, int params[])
2164{
2165 int heads;
2166 int sectors;
2167 sector_t cylinders;
2168 ulong dummy;
2169
2170 heads = 64;
2171 sectors = 32;
2172
2173 dummy = heads * sectors;
2174 cylinders = capacity;
2175 sector_div(cylinders, dummy);
2176
2177 /*
2178 * Handle extended translation size for logical drives
2179 * > 1Gb
2180 */
2181 if ((ulong)capacity >= 0x200000) {
2182 heads = 255;
2183 sectors = 63;
2184 dummy = heads * sectors;
2185 cylinders = capacity;
2186 sector_div(cylinders, dummy);
2187 }
2188
2189 /* return result */
2190 params[0] = heads;
2191 params[1] = sectors;
2192 params[2] = cylinders;
2193
2194 return 0;
2195}
2196
2197/**
2198 * _scsih_response_code - translation of device response code
2199 * @ioc: per adapter object
2200 * @response_code: response code returned by the device
2201 *
2202 * Return nothing.
2203 */
2204static void
2205_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
2206{
2207 char *desc;
2208
2209 switch (response_code) {
2210 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2211 desc = "task management request completed";
2212 break;
2213 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2214 desc = "invalid frame";
2215 break;
2216 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2217 desc = "task management request not supported";
2218 break;
2219 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2220 desc = "task management request failed";
2221 break;
2222 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2223 desc = "task management request succeeded";
2224 break;
2225 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2226 desc = "invalid lun";
2227 break;
2228 case 0xA:
2229 desc = "overlapped tag attempted";
2230 break;
2231 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2232 desc = "task queued, however not sent to target";
2233 break;
2234 default:
2235 desc = "unknown";
2236 break;
2237 }
2238 printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n",
2239 ioc->name, response_code, desc);
2240}
2241
2242/**
Eric Moored5d135b2009-05-18 13:02:08 -06002243 * _scsih_tm_done - tm completion routine
Eric Moore635374e2009-03-09 01:21:12 -06002244 * @ioc: per adapter object
2245 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302246 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -06002247 * @reply: reply message frame(lower 32bit addr)
2248 * Context: none.
2249 *
2250 * The callback handler when using scsih_issue_tm.
2251 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302252 * Return 1 meaning mf should be freed from _base_interrupt
2253 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -06002254 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302255static u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302256_scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -06002257{
2258 MPI2DefaultReply_t *mpi_reply;
2259
2260 if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302261 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002262 if (ioc->tm_cmds.smid != smid)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302263 return 1;
nagalakshmi.nandigama@lsi.com911ae942011-09-08 06:18:50 +05302264 mpt2sas_base_flush_reply_queues(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06002265 ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
2266 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
2267 if (mpi_reply) {
2268 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
2269 ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID;
2270 }
2271 ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
2272 complete(&ioc->tm_cmds.done);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302273 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002274}
2275
2276/**
2277 * mpt2sas_scsih_set_tm_flag - set per target tm_busy
2278 * @ioc: per adapter object
2279 * @handle: device handle
2280 *
2281 * During taskmangement request, we need to freeze the device queue.
2282 */
2283void
2284mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2285{
2286 struct MPT2SAS_DEVICE *sas_device_priv_data;
2287 struct scsi_device *sdev;
2288 u8 skip = 0;
2289
2290 shost_for_each_device(sdev, ioc->shost) {
2291 if (skip)
2292 continue;
2293 sas_device_priv_data = sdev->hostdata;
2294 if (!sas_device_priv_data)
2295 continue;
2296 if (sas_device_priv_data->sas_target->handle == handle) {
2297 sas_device_priv_data->sas_target->tm_busy = 1;
2298 skip = 1;
2299 ioc->ignore_loginfos = 1;
2300 }
2301 }
2302}
2303
2304/**
2305 * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy
2306 * @ioc: per adapter object
2307 * @handle: device handle
2308 *
2309 * During taskmangement request, we need to freeze the device queue.
2310 */
2311void
2312mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2313{
2314 struct MPT2SAS_DEVICE *sas_device_priv_data;
2315 struct scsi_device *sdev;
2316 u8 skip = 0;
2317
2318 shost_for_each_device(sdev, ioc->shost) {
2319 if (skip)
2320 continue;
2321 sas_device_priv_data = sdev->hostdata;
2322 if (!sas_device_priv_data)
2323 continue;
2324 if (sas_device_priv_data->sas_target->handle == handle) {
2325 sas_device_priv_data->sas_target->tm_busy = 0;
2326 skip = 1;
2327 ioc->ignore_loginfos = 0;
2328 }
2329 }
2330}
2331
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302332
Eric Moore635374e2009-03-09 01:21:12 -06002333/**
2334 * mpt2sas_scsih_issue_tm - main routine for sending tm requests
2335 * @ioc: per adapter struct
2336 * @device_handle: device handle
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302337 * @channel: the channel assigned by the OS
2338 * @id: the id assigned by the OS
Eric Moore635374e2009-03-09 01:21:12 -06002339 * @lun: lun number
2340 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2341 * @smid_task: smid assigned to the task
2342 * @timeout: timeout in seconds
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302343 * @serial_number: the serial_number from scmd
2344 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302345 * Context: user
Eric Moore635374e2009-03-09 01:21:12 -06002346 *
2347 * A generic API for sending task management requests to firmware.
2348 *
Eric Moore635374e2009-03-09 01:21:12 -06002349 * The callback index is set inside `ioc->tm_cb_idx`.
2350 *
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302351 * Return SUCCESS or FAILED.
Eric Moore635374e2009-03-09 01:21:12 -06002352 */
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302353int
2354mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2355 uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302356 unsigned long serial_number, enum mutex_type m_type)
Eric Moore635374e2009-03-09 01:21:12 -06002357{
2358 Mpi2SCSITaskManagementRequest_t *mpi_request;
2359 Mpi2SCSITaskManagementReply_t *mpi_reply;
2360 u16 smid = 0;
2361 u32 ioc_state;
2362 unsigned long timeleft;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302363 struct scsiio_tracker *scsi_lookup = NULL;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302364 int rc;
Eric Moore635374e2009-03-09 01:21:12 -06002365
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302366 if (m_type == TM_MUTEX_ON)
2367 mutex_lock(&ioc->tm_cmds.mutex);
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05302368 if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
2369 printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
2370 __func__, ioc->name);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302371 rc = FAILED;
2372 goto err_out;
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05302373 }
2374
Eric Moore3cb54692010-07-08 14:44:34 -06002375 if (ioc->shost_recovery || ioc->remove_host ||
2376 ioc->pci_error_recovery) {
Eric Moore635374e2009-03-09 01:21:12 -06002377 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
2378 __func__, ioc->name);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302379 rc = FAILED;
2380 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002381 }
Eric Moore635374e2009-03-09 01:21:12 -06002382
2383 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
2384 if (ioc_state & MPI2_DOORBELL_USED) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302385 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
Eric Moore635374e2009-03-09 01:21:12 -06002386 "active!\n", ioc->name));
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302387 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302388 FORCE_BIG_HAMMER);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302389 rc = (!rc) ? SUCCESS : FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302390 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002391 }
2392
2393 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2394 mpt2sas_base_fault_info(ioc, ioc_state &
2395 MPI2_DOORBELL_DATA_MASK);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302396 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302397 FORCE_BIG_HAMMER);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302398 rc = (!rc) ? SUCCESS : FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302399 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002400 }
2401
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302402 smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
Eric Moore635374e2009-03-09 01:21:12 -06002403 if (!smid) {
2404 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2405 ioc->name, __func__);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302406 rc = FAILED;
2407 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002408 }
2409
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302410 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2411 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2412
Eric Moore635374e2009-03-09 01:21:12 -06002413 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302414 " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
2415 smid_task));
Eric Moore635374e2009-03-09 01:21:12 -06002416 ioc->tm_cmds.status = MPT2_CMD_PENDING;
2417 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2418 ioc->tm_cmds.smid = smid;
2419 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302420 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
Eric Moore635374e2009-03-09 01:21:12 -06002421 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2422 mpi_request->DevHandle = cpu_to_le16(handle);
2423 mpi_request->TaskType = type;
2424 mpi_request->TaskMID = cpu_to_le16(smid_task);
2425 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
2426 mpt2sas_scsih_set_tm_flag(ioc, handle);
Kashyap, Desai5b768582009-08-20 13:24:31 +05302427 init_completion(&ioc->tm_cmds.done);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302428 mpt2sas_base_put_smid_hi_priority(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06002429 timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
Eric Moore635374e2009-03-09 01:21:12 -06002430 if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
2431 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2432 ioc->name, __func__);
2433 _debug_dump_mf(mpi_request,
2434 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302435 if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302436 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302437 FORCE_BIG_HAMMER);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302438 rc = (!rc) ? SUCCESS : FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302439 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
2440 mpt2sas_scsih_clear_tm_flag(ioc, handle);
2441 goto err_out;
2442 }
Eric Moore635374e2009-03-09 01:21:12 -06002443 }
2444
2445 if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) {
2446 mpi_reply = ioc->tm_cmds.reply;
2447 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: "
2448 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
2449 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
2450 le32_to_cpu(mpi_reply->IOCLogInfo),
2451 le32_to_cpu(mpi_reply->TerminationCount)));
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302452 if (ioc->logging_level & MPT_DEBUG_TM) {
Eric Moore635374e2009-03-09 01:21:12 -06002453 _scsih_response_code(ioc, mpi_reply->ResponseCode);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302454 if (mpi_reply->IOCStatus)
2455 _debug_dump_mf(mpi_request,
2456 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2457 }
Eric Moore635374e2009-03-09 01:21:12 -06002458 }
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302459
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302460 switch (type) {
2461 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302462 rc = SUCCESS;
2463 if (scsi_lookup->scmd == NULL)
2464 break;
2465 rc = FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302466 break;
2467
2468 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2469 if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
2470 rc = FAILED;
2471 else
2472 rc = SUCCESS;
2473 break;
2474
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302475 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302476 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2477 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2478 rc = FAILED;
2479 else
2480 rc = SUCCESS;
2481 break;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302482 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2483 rc = SUCCESS;
2484 break;
2485 default:
2486 rc = FAILED;
2487 break;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302488 }
2489
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302490 mpt2sas_scsih_clear_tm_flag(ioc, handle);
2491 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302492 if (m_type == TM_MUTEX_ON)
2493 mutex_unlock(&ioc->tm_cmds.mutex);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302494
2495 return rc;
2496
2497 err_out:
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302498 if (m_type == TM_MUTEX_ON)
2499 mutex_unlock(&ioc->tm_cmds.mutex);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302500 return rc;
Eric Moore635374e2009-03-09 01:21:12 -06002501}
2502
2503/**
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302504 * _scsih_tm_display_info - displays info about the device
2505 * @ioc: per adapter struct
2506 * @scmd: pointer to scsi command object
2507 *
2508 * Called by task management callback handlers.
2509 */
2510static void
2511_scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
2512{
2513 struct scsi_target *starget = scmd->device->sdev_target;
2514 struct MPT2SAS_TARGET *priv_target = starget->hostdata;
2515 struct _sas_device *sas_device = NULL;
2516 unsigned long flags;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302517 char *device_str = NULL;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302518
2519 if (!priv_target)
2520 return;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302521 if (ioc->hide_ir_msg)
2522 device_str = "WarpDrive";
2523 else
2524 device_str = "volume";
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302525
2526 scsi_print_command(scmd);
2527 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302528 starget_printk(KERN_INFO, starget, "%s handle(0x%04x), "
2529 "%s wwid(0x%016llx)\n", device_str, priv_target->handle,
2530 device_str, (unsigned long long)priv_target->sas_address);
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302531 } else {
2532 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2533 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
2534 priv_target->sas_address);
2535 if (sas_device) {
2536 if (priv_target->flags &
2537 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2538 starget_printk(KERN_INFO, starget,
2539 "volume handle(0x%04x), "
2540 "volume wwid(0x%016llx)\n",
2541 sas_device->volume_handle,
2542 (unsigned long long)sas_device->volume_wwid);
2543 }
2544 starget_printk(KERN_INFO, starget,
2545 "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
2546 sas_device->handle,
2547 (unsigned long long)sas_device->sas_address,
2548 sas_device->phy);
2549 starget_printk(KERN_INFO, starget,
2550 "enclosure_logical_id(0x%016llx), slot(%d)\n",
2551 (unsigned long long)sas_device->enclosure_logical_id,
2552 sas_device->slot);
2553 }
2554 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2555 }
2556}
2557
2558/**
Eric Moored5d135b2009-05-18 13:02:08 -06002559 * _scsih_abort - eh threads main abort routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302560 * @scmd: pointer to scsi command object
Eric Moore635374e2009-03-09 01:21:12 -06002561 *
2562 * Returns SUCCESS if command aborted else FAILED
2563 */
2564static int
Eric Moored5d135b2009-05-18 13:02:08 -06002565_scsih_abort(struct scsi_cmnd *scmd)
Eric Moore635374e2009-03-09 01:21:12 -06002566{
2567 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2568 struct MPT2SAS_DEVICE *sas_device_priv_data;
2569 u16 smid;
2570 u16 handle;
2571 int r;
Eric Moore635374e2009-03-09 01:21:12 -06002572
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302573 sdev_printk(KERN_INFO, scmd->device, "attempting task abort! "
2574 "scmd(%p)\n", scmd);
2575 _scsih_tm_display_info(ioc, scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002576
2577 sas_device_priv_data = scmd->device->hostdata;
2578 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302579 sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
2580 "scmd(%p)\n", scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002581 scmd->result = DID_NO_CONNECT << 16;
2582 scmd->scsi_done(scmd);
2583 r = SUCCESS;
2584 goto out;
2585 }
2586
2587 /* search for the command */
2588 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
2589 if (!smid) {
2590 scmd->result = DID_RESET << 16;
2591 r = SUCCESS;
2592 goto out;
2593 }
2594
2595 /* for hidden raid components and volumes this is not supported */
2596 if (sas_device_priv_data->sas_target->flags &
2597 MPT_TARGET_FLAGS_RAID_COMPONENT ||
2598 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2599 scmd->result = DID_RESET << 16;
2600 r = FAILED;
2601 goto out;
2602 }
2603
Kashyap, Desaifa7f3162009-09-23 17:26:58 +05302604 mpt2sas_halt_firmware(ioc);
2605
Eric Moore635374e2009-03-09 01:21:12 -06002606 handle = sas_device_priv_data->sas_target->handle;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302607 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2608 scmd->device->id, scmd->device->lun,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302609 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
2610 scmd->serial_number, TM_MUTEX_ON);
Eric Moore635374e2009-03-09 01:21:12 -06002611
2612 out:
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302613 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
2614 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002615 return r;
2616}
2617
Eric Moore635374e2009-03-09 01:21:12 -06002618/**
Eric Moored5d135b2009-05-18 13:02:08 -06002619 * _scsih_dev_reset - eh threads main device reset routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302620 * @scmd: pointer to scsi command object
Eric Moore635374e2009-03-09 01:21:12 -06002621 *
2622 * Returns SUCCESS if command aborted else FAILED
2623 */
2624static int
Eric Moored5d135b2009-05-18 13:02:08 -06002625_scsih_dev_reset(struct scsi_cmnd *scmd)
Eric Moore635374e2009-03-09 01:21:12 -06002626{
2627 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2628 struct MPT2SAS_DEVICE *sas_device_priv_data;
2629 struct _sas_device *sas_device;
2630 unsigned long flags;
2631 u16 handle;
2632 int r;
2633
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302634 struct scsi_target *starget = scmd->device->sdev_target;
2635
Kashyap, Desai37aaa782010-11-13 04:41:32 +05302636 starget_printk(KERN_INFO, starget, "attempting device reset! "
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302637 "scmd(%p)\n", scmd);
2638 _scsih_tm_display_info(ioc, scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002639
2640 sas_device_priv_data = scmd->device->hostdata;
2641 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Kashyap, Desai37aaa782010-11-13 04:41:32 +05302642 starget_printk(KERN_INFO, starget, "device been deleted! "
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302643 "scmd(%p)\n", scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002644 scmd->result = DID_NO_CONNECT << 16;
2645 scmd->scsi_done(scmd);
2646 r = SUCCESS;
2647 goto out;
2648 }
2649
2650 /* for hidden raid components obtain the volume_handle */
2651 handle = 0;
2652 if (sas_device_priv_data->sas_target->flags &
2653 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2654 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2655 sas_device = _scsih_sas_device_find_by_handle(ioc,
2656 sas_device_priv_data->sas_target->handle);
2657 if (sas_device)
2658 handle = sas_device->volume_handle;
2659 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2660 } else
2661 handle = sas_device_priv_data->sas_target->handle;
2662
2663 if (!handle) {
2664 scmd->result = DID_RESET << 16;
2665 r = FAILED;
2666 goto out;
2667 }
2668
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302669 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2670 scmd->device->id, scmd->device->lun,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302671 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
2672 TM_MUTEX_ON);
Eric Moore993e0da2009-05-18 13:00:45 -06002673
2674 out:
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302675 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
2676 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Eric Moore993e0da2009-05-18 13:00:45 -06002677 return r;
2678}
2679
2680/**
Eric Moored5d135b2009-05-18 13:02:08 -06002681 * _scsih_target_reset - eh threads main target reset routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302682 * @scmd: pointer to scsi command object
Eric Moore993e0da2009-05-18 13:00:45 -06002683 *
2684 * Returns SUCCESS if command aborted else FAILED
2685 */
2686static int
Eric Moored5d135b2009-05-18 13:02:08 -06002687_scsih_target_reset(struct scsi_cmnd *scmd)
Eric Moore993e0da2009-05-18 13:00:45 -06002688{
2689 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2690 struct MPT2SAS_DEVICE *sas_device_priv_data;
2691 struct _sas_device *sas_device;
2692 unsigned long flags;
2693 u16 handle;
2694 int r;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302695 struct scsi_target *starget = scmd->device->sdev_target;
Eric Moore993e0da2009-05-18 13:00:45 -06002696
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302697 starget_printk(KERN_INFO, starget, "attempting target reset! "
2698 "scmd(%p)\n", scmd);
2699 _scsih_tm_display_info(ioc, scmd);
Eric Moore993e0da2009-05-18 13:00:45 -06002700
2701 sas_device_priv_data = scmd->device->hostdata;
2702 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302703 starget_printk(KERN_INFO, starget, "target been deleted! "
2704 "scmd(%p)\n", scmd);
Eric Moore993e0da2009-05-18 13:00:45 -06002705 scmd->result = DID_NO_CONNECT << 16;
2706 scmd->scsi_done(scmd);
2707 r = SUCCESS;
2708 goto out;
2709 }
2710
2711 /* for hidden raid components obtain the volume_handle */
2712 handle = 0;
2713 if (sas_device_priv_data->sas_target->flags &
2714 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2715 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2716 sas_device = _scsih_sas_device_find_by_handle(ioc,
2717 sas_device_priv_data->sas_target->handle);
2718 if (sas_device)
2719 handle = sas_device->volume_handle;
2720 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2721 } else
2722 handle = sas_device_priv_data->sas_target->handle;
2723
2724 if (!handle) {
2725 scmd->result = DID_RESET << 16;
2726 r = FAILED;
2727 goto out;
2728 }
2729
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302730 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2731 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302732 30, 0, TM_MUTEX_ON);
Eric Moore635374e2009-03-09 01:21:12 -06002733
2734 out:
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302735 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
2736 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002737 return r;
2738}
2739
2740/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302741 * _scsih_host_reset - eh threads main host reset routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302742 * @scmd: pointer to scsi command object
Eric Moore635374e2009-03-09 01:21:12 -06002743 *
2744 * Returns SUCCESS if command aborted else FAILED
2745 */
2746static int
Eric Moored5d135b2009-05-18 13:02:08 -06002747_scsih_host_reset(struct scsi_cmnd *scmd)
Eric Moore635374e2009-03-09 01:21:12 -06002748{
2749 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2750 int r, retval;
2751
2752 printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n",
2753 ioc->name, scmd);
2754 scsi_print_command(scmd);
2755
2756 retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2757 FORCE_BIG_HAMMER);
2758 r = (retval < 0) ? FAILED : SUCCESS;
2759 printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n",
2760 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2761
2762 return r;
2763}
2764
2765/**
2766 * _scsih_fw_event_add - insert and queue up fw_event
2767 * @ioc: per adapter object
2768 * @fw_event: object describing the event
2769 * Context: This function will acquire ioc->fw_event_lock.
2770 *
2771 * This adds the firmware event object into link list, then queues it up to
2772 * be processed from user context.
2773 *
2774 * Return nothing.
2775 */
2776static void
2777_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2778{
2779 unsigned long flags;
2780
2781 if (ioc->firmware_event_thread == NULL)
2782 return;
2783
2784 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2785 list_add_tail(&fw_event->list, &ioc->fw_event_list);
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302786 INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work);
2787 queue_delayed_work(ioc->firmware_event_thread,
2788 &fw_event->delayed_work, 0);
Eric Moore635374e2009-03-09 01:21:12 -06002789 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2790}
2791
2792/**
2793 * _scsih_fw_event_free - delete fw_event
2794 * @ioc: per adapter object
2795 * @fw_event: object describing the event
2796 * Context: This function will acquire ioc->fw_event_lock.
2797 *
2798 * This removes firmware event object from link list, frees associated memory.
2799 *
2800 * Return nothing.
2801 */
2802static void
2803_scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
2804 *fw_event)
2805{
2806 unsigned long flags;
2807
2808 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2809 list_del(&fw_event->list);
2810 kfree(fw_event->event_data);
2811 kfree(fw_event);
2812 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2813}
2814
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302815
Eric Moore635374e2009-03-09 01:21:12 -06002816/**
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302817 * _scsih_error_recovery_delete_devices - remove devices not responding
Eric Moore635374e2009-03-09 01:21:12 -06002818 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06002819 *
2820 * Return nothing.
2821 */
2822static void
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302823_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
Eric Moore635374e2009-03-09 01:21:12 -06002824{
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302825 struct fw_event_work *fw_event;
2826
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302827 if (ioc->is_driver_loading)
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302828 return;
Dan Carpenter181a9d72011-11-04 21:25:01 +03002829
2830 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2831 if (!fw_event)
2832 return;
2833
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302834 fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
2835 fw_event->ioc = ioc;
2836 _scsih_fw_event_add(ioc, fw_event);
2837}
2838
2839/**
2840 * mpt2sas_port_enable_complete - port enable completed (fake event)
2841 * @ioc: per adapter object
2842 *
2843 * Return nothing.
2844 */
2845void
2846mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
2847{
2848 struct fw_event_work *fw_event;
2849
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302850 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2851 if (!fw_event)
2852 return;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302853 fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302854 fw_event->ioc = ioc;
2855 _scsih_fw_event_add(ioc, fw_event);
2856}
2857
2858/**
2859 * _scsih_fw_event_cleanup_queue - cleanup event queue
2860 * @ioc: per adapter object
2861 *
2862 * Walk the firmware event queue, either killing timers, or waiting
2863 * for outstanding events to complete
2864 *
2865 * Return nothing.
2866 */
2867static void
2868_scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
2869{
2870 struct fw_event_work *fw_event, *next;
2871
2872 if (list_empty(&ioc->fw_event_list) ||
2873 !ioc->firmware_event_thread || in_interrupt())
Eric Moore635374e2009-03-09 01:21:12 -06002874 return;
2875
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302876 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
2877 if (cancel_delayed_work(&fw_event->delayed_work)) {
2878 _scsih_fw_event_free(ioc, fw_event);
2879 continue;
2880 }
2881 fw_event->cancel_pending_work = 1;
2882 }
Eric Moore635374e2009-03-09 01:21:12 -06002883}
2884
Eric Moore635374e2009-03-09 01:21:12 -06002885/**
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302886 * _scsih_ublock_io_all_device - unblock every device
2887 * @ioc: per adapter object
2888 *
2889 * change the device state from block to running
2890 */
2891static void
2892_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2893{
2894 struct MPT2SAS_DEVICE *sas_device_priv_data;
2895 struct scsi_device *sdev;
2896
2897 shost_for_each_device(sdev, ioc->shost) {
2898 sas_device_priv_data = sdev->hostdata;
2899 if (!sas_device_priv_data)
2900 continue;
2901 if (!sas_device_priv_data->block)
2902 continue;
2903 sas_device_priv_data->block = 0;
2904 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
2905 "handle(0x%04x)\n",
2906 sas_device_priv_data->sas_target->handle));
2907 scsi_internal_device_unblock(sdev);
2908 }
2909}
2910/**
Eric Moore635374e2009-03-09 01:21:12 -06002911 * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
2912 * @ioc: per adapter object
2913 * @handle: device handle
2914 *
2915 * During device pull we need to appropiately set the sdev state.
2916 */
2917static void
2918_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2919{
2920 struct MPT2SAS_DEVICE *sas_device_priv_data;
2921 struct scsi_device *sdev;
2922
2923 shost_for_each_device(sdev, ioc->shost) {
2924 sas_device_priv_data = sdev->hostdata;
2925 if (!sas_device_priv_data)
2926 continue;
2927 if (!sas_device_priv_data->block)
2928 continue;
2929 if (sas_device_priv_data->sas_target->handle == handle) {
2930 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2931 MPT2SAS_INFO_FMT "SDEV_RUNNING: "
2932 "handle(0x%04x)\n", ioc->name, handle));
2933 sas_device_priv_data->block = 0;
Kashyap, Desai34a03be2009-08-20 13:23:19 +05302934 scsi_internal_device_unblock(sdev);
Eric Moore635374e2009-03-09 01:21:12 -06002935 }
2936 }
2937}
2938
2939/**
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302940 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2941 * @ioc: per adapter object
2942 * @handle: device handle
2943 *
2944 * During device pull we need to appropiately set the sdev state.
2945 */
2946static void
2947_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2948{
2949 struct MPT2SAS_DEVICE *sas_device_priv_data;
2950 struct scsi_device *sdev;
2951
2952 shost_for_each_device(sdev, ioc->shost) {
2953 sas_device_priv_data = sdev->hostdata;
2954 if (!sas_device_priv_data)
2955 continue;
2956 if (sas_device_priv_data->block)
2957 continue;
2958 sas_device_priv_data->block = 1;
2959 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
2960 "handle(0x%04x)\n",
2961 sas_device_priv_data->sas_target->handle));
2962 scsi_internal_device_block(sdev);
2963 }
2964}
2965
2966
2967/**
Eric Moore635374e2009-03-09 01:21:12 -06002968 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2969 * @ioc: per adapter object
2970 * @handle: device handle
2971 *
2972 * During device pull we need to appropiately set the sdev state.
2973 */
2974static void
2975_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2976{
2977 struct MPT2SAS_DEVICE *sas_device_priv_data;
2978 struct scsi_device *sdev;
2979
2980 shost_for_each_device(sdev, ioc->shost) {
2981 sas_device_priv_data = sdev->hostdata;
2982 if (!sas_device_priv_data)
2983 continue;
2984 if (sas_device_priv_data->block)
2985 continue;
2986 if (sas_device_priv_data->sas_target->handle == handle) {
2987 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2988 MPT2SAS_INFO_FMT "SDEV_BLOCK: "
2989 "handle(0x%04x)\n", ioc->name, handle));
2990 sas_device_priv_data->block = 1;
Kashyap, Desai34a03be2009-08-20 13:23:19 +05302991 scsi_internal_device_block(sdev);
Eric Moore635374e2009-03-09 01:21:12 -06002992 }
2993 }
2994}
2995
2996/**
2997 * _scsih_block_io_to_children_attached_to_ex
2998 * @ioc: per adapter object
2999 * @sas_expander: the sas_device object
3000 *
3001 * This routine set sdev state to SDEV_BLOCK for all devices
3002 * attached to this expander. This function called when expander is
3003 * pulled.
3004 */
3005static void
3006_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
3007 struct _sas_node *sas_expander)
3008{
3009 struct _sas_port *mpt2sas_port;
3010 struct _sas_device *sas_device;
3011 struct _sas_node *expander_sibling;
3012 unsigned long flags;
3013
3014 if (!sas_expander)
3015 return;
3016
3017 list_for_each_entry(mpt2sas_port,
3018 &sas_expander->sas_port_list, port_list) {
3019 if (mpt2sas_port->remote_identify.device_type ==
3020 SAS_END_DEVICE) {
3021 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3022 sas_device =
3023 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
3024 mpt2sas_port->remote_identify.sas_address);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05303025 if (sas_device)
3026 set_bit(sas_device->handle,
3027 ioc->blocking_handles);
Eric Moore635374e2009-03-09 01:21:12 -06003028 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06003029 }
3030 }
3031
3032 list_for_each_entry(mpt2sas_port,
3033 &sas_expander->sas_port_list, port_list) {
3034
3035 if (mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05303036 SAS_EDGE_EXPANDER_DEVICE ||
Eric Moore635374e2009-03-09 01:21:12 -06003037 mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05303038 SAS_FANOUT_EXPANDER_DEVICE) {
Eric Moore635374e2009-03-09 01:21:12 -06003039 expander_sibling =
3040 mpt2sas_scsih_expander_find_by_sas_address(
3041 ioc, mpt2sas_port->remote_identify.sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06003042 _scsih_block_io_to_children_attached_to_ex(ioc,
3043 expander_sibling);
3044 }
3045 }
3046}
3047
3048/**
3049 * _scsih_block_io_to_children_attached_directly
3050 * @ioc: per adapter object
3051 * @event_data: topology change event data
3052 *
3053 * This routine set sdev state to SDEV_BLOCK for all devices
3054 * direct attached during device pull.
3055 */
3056static void
3057_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
3058 Mpi2EventDataSasTopologyChangeList_t *event_data)
3059{
3060 int i;
3061 u16 handle;
3062 u16 reason_code;
3063 u8 phy_number;
3064
3065 for (i = 0; i < event_data->NumEntries; i++) {
3066 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3067 if (!handle)
3068 continue;
3069 phy_number = event_data->StartPhyNum + i;
3070 reason_code = event_data->PHY[i].PhyStatus &
3071 MPI2_EVENT_SAS_TOPO_RC_MASK;
3072 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
3073 _scsih_block_io_device(ioc, handle);
3074 }
3075}
3076
3077/**
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303078 * _scsih_tm_tr_send - send task management request
3079 * @ioc: per adapter object
3080 * @handle: device handle
3081 * Context: interrupt time.
3082 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003083 * This code is to initiate the device removal handshake protocol
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303084 * with controller firmware. This function will issue target reset
3085 * using high priority request queue. It will send a sas iounit
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003086 * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303087 *
3088 * This is designed to send muliple task management request at the same
3089 * time to the fifo. If the fifo is full, we will append the request,
3090 * and process it in a future completion.
3091 */
3092static void
3093_scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3094{
3095 Mpi2SCSITaskManagementRequest_t *mpi_request;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303096 u16 smid;
3097 struct _sas_device *sas_device;
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303098 struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
3099 u64 sas_address = 0;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303100 unsigned long flags;
3101 struct _tr_list *delayed_tr;
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303102 u32 ioc_state;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303103
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303104 if (ioc->remove_host) {
3105 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
3106 "removed: handle(0x%04x)\n", __func__, ioc->name, handle));
3107 return;
3108 } else if (ioc->pci_error_recovery) {
3109 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
3110 "error recovery: handle(0x%04x)\n", __func__, ioc->name,
3111 handle));
3112 return;
3113 }
3114 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
3115 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3116 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
3117 "operational: handle(0x%04x)\n", __func__, ioc->name,
3118 handle));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303119 return;
3120 }
3121
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303122 /* if PD, then return */
3123 if (test_bit(handle, ioc->pd_handles))
3124 return;
3125
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303126 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3127 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303128 if (sas_device && sas_device->starget &&
3129 sas_device->starget->hostdata) {
3130 sas_target_priv_data = sas_device->starget->hostdata;
3131 sas_target_priv_data->deleted = 1;
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303132 sas_address = sas_device->sas_address;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303133 }
3134 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303135
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303136 if (sas_target_priv_data) {
3137 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
3138 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
3139 (unsigned long long)sas_address));
3140 _scsih_ublock_io_device(ioc, handle);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05303141 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303142 }
3143
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303144 smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
3145 if (!smid) {
3146 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3147 if (!delayed_tr)
3148 return;
3149 INIT_LIST_HEAD(&delayed_tr->list);
3150 delayed_tr->handle = handle;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303151 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3152 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3153 "DELAYED:tr:handle(0x%04x), (open)\n",
3154 ioc->name, handle));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303155 return;
3156 }
3157
Kashyap, Desai1278b112010-03-09 17:34:13 +05303158 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
3159 "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
3160 ioc->tm_tr_cb_idx));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303161 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3162 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3163 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3164 mpi_request->DevHandle = cpu_to_le16(handle);
3165 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303166 mpt2sas_base_put_smid_hi_priority(ioc, smid);
3167}
3168
3169
3170
3171/**
3172 * _scsih_sas_control_complete - completion routine
3173 * @ioc: per adapter object
3174 * @smid: system request message index
3175 * @msix_index: MSIX table index supplied by the OS
3176 * @reply: reply message frame(lower 32bit addr)
3177 * Context: interrupt time.
3178 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003179 * This is the sas iounit control completion routine.
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303180 * This code is part of the code to initiate the device removal
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003181 * handshake protocol with controller firmware.
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303182 *
3183 * Return 1 meaning mf should be freed from _base_interrupt
3184 * 0 means the mf is freed from this function.
3185 */
3186static u8
3187_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
3188 u8 msix_index, u32 reply)
3189{
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303190 Mpi2SasIoUnitControlReply_t *mpi_reply =
3191 mpt2sas_base_get_reply_virt_addr(ioc, reply);
nagalakshmi.nandigama@lsi.com298c7942012-03-20 12:07:17 +05303192 if (likely(mpi_reply)) {
3193 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3194 "sc_complete:handle(0x%04x), (open) "
3195 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
3196 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
3197 le16_to_cpu(mpi_reply->IOCStatus),
3198 le32_to_cpu(mpi_reply->IOCLogInfo)));
3199 } else {
3200 printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3201 ioc->name, __FILE__, __LINE__, __func__);
3202 }
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303203 return 1;
3204}
3205
3206/**
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303207 * _scsih_tm_tr_volume_send - send target reset request for volumes
3208 * @ioc: per adapter object
3209 * @handle: device handle
3210 * Context: interrupt time.
3211 *
3212 * This is designed to send muliple task management request at the same
3213 * time to the fifo. If the fifo is full, we will append the request,
3214 * and process it in a future completion.
3215 */
3216static void
3217_scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3218{
3219 Mpi2SCSITaskManagementRequest_t *mpi_request;
3220 u16 smid;
3221 struct _tr_list *delayed_tr;
3222
Eric Moore3cb54692010-07-08 14:44:34 -06003223 if (ioc->shost_recovery || ioc->remove_host ||
3224 ioc->pci_error_recovery) {
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303225 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
3226 "progress!\n", __func__, ioc->name));
3227 return;
3228 }
3229
3230 smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3231 if (!smid) {
3232 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3233 if (!delayed_tr)
3234 return;
3235 INIT_LIST_HEAD(&delayed_tr->list);
3236 delayed_tr->handle = handle;
3237 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3238 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3239 "DELAYED:tr:handle(0x%04x), (open)\n",
3240 ioc->name, handle));
3241 return;
3242 }
3243
3244 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
3245 "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
3246 ioc->tm_tr_volume_cb_idx));
3247 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3248 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3249 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3250 mpi_request->DevHandle = cpu_to_le16(handle);
3251 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3252 mpt2sas_base_put_smid_hi_priority(ioc, smid);
3253}
3254
3255/**
3256 * _scsih_tm_volume_tr_complete - target reset completion
3257 * @ioc: per adapter object
3258 * @smid: system request message index
3259 * @msix_index: MSIX table index supplied by the OS
3260 * @reply: reply message frame(lower 32bit addr)
3261 * Context: interrupt time.
3262 *
3263 * Return 1 meaning mf should be freed from _base_interrupt
3264 * 0 means the mf is freed from this function.
3265 */
3266static u8
3267_scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
3268 u8 msix_index, u32 reply)
3269{
3270 u16 handle;
3271 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3272 Mpi2SCSITaskManagementReply_t *mpi_reply =
3273 mpt2sas_base_get_reply_virt_addr(ioc, reply);
3274
Eric Moore3cb54692010-07-08 14:44:34 -06003275 if (ioc->shost_recovery || ioc->remove_host ||
3276 ioc->pci_error_recovery) {
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303277 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
3278 "progress!\n", __func__, ioc->name));
3279 return 1;
3280 }
nagalakshmi.nandigama@lsi.com298c7942012-03-20 12:07:17 +05303281 if (unlikely(!mpi_reply)) {
3282 printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3283 ioc->name, __FILE__, __LINE__, __func__);
3284 return 1;
3285 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303286 mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
3287 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3288 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3289 dewtprintk(ioc, printk("spurious interrupt: "
3290 "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle,
3291 le16_to_cpu(mpi_reply->DevHandle), smid));
3292 return 0;
3293 }
3294
3295 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3296 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3297 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3298 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3299 le32_to_cpu(mpi_reply->IOCLogInfo),
3300 le32_to_cpu(mpi_reply->TerminationCount)));
3301
3302 return _scsih_check_for_pending_tm(ioc, smid);
3303}
3304
3305/**
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303306 * _scsih_tm_tr_complete -
3307 * @ioc: per adapter object
3308 * @smid: system request message index
3309 * @msix_index: MSIX table index supplied by the OS
3310 * @reply: reply message frame(lower 32bit addr)
3311 * Context: interrupt time.
3312 *
3313 * This is the target reset completion routine.
3314 * This code is part of the code to initiate the device removal
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003315 * handshake protocol with controller firmware.
3316 * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303317 *
3318 * Return 1 meaning mf should be freed from _base_interrupt
3319 * 0 means the mf is freed from this function.
3320 */
3321static u8
3322_scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
3323 u32 reply)
3324{
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303325 u16 handle;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303326 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303327 Mpi2SCSITaskManagementReply_t *mpi_reply =
3328 mpt2sas_base_get_reply_virt_addr(ioc, reply);
3329 Mpi2SasIoUnitControlRequest_t *mpi_request;
3330 u16 smid_sas_ctrl;
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303331 u32 ioc_state;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303332
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303333 if (ioc->remove_host) {
3334 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
3335 "removed\n", __func__, ioc->name));
3336 return 1;
3337 } else if (ioc->pci_error_recovery) {
3338 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
3339 "error recovery\n", __func__, ioc->name));
3340 return 1;
3341 }
3342 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
3343 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3344 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
3345 "operational\n", __func__, ioc->name));
Kashyap, Desai1278b112010-03-09 17:34:13 +05303346 return 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303347 }
nagalakshmi.nandigama@lsi.com298c7942012-03-20 12:07:17 +05303348 if (unlikely(!mpi_reply)) {
3349 printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3350 ioc->name, __FILE__, __LINE__, __func__);
3351 return 1;
3352 }
Kashyap, Desai1278b112010-03-09 17:34:13 +05303353 mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
3354 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3355 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3356 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "spurious interrupt: "
3357 "handle(0x%04x:0x%04x), smid(%d)!!!\n", ioc->name, handle,
3358 le16_to_cpu(mpi_reply->DevHandle), smid));
3359 return 0;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303360 }
3361
Kashyap, Desai1278b112010-03-09 17:34:13 +05303362 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3363 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3364 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3365 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3366 le32_to_cpu(mpi_reply->IOCLogInfo),
3367 le32_to_cpu(mpi_reply->TerminationCount)));
3368
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303369 smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
3370 if (!smid_sas_ctrl) {
3371 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3372 ioc->name, __func__);
Kashyap, Desai1278b112010-03-09 17:34:13 +05303373 return 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303374 }
3375
Kashyap, Desai1278b112010-03-09 17:34:13 +05303376 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sc_send:handle(0x%04x), "
3377 "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid_sas_ctrl,
3378 ioc->tm_sas_control_cb_idx));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303379 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl);
3380 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3381 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3382 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303383 mpi_request->DevHandle = mpi_request_tm->DevHandle;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303384 mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl);
Kashyap, Desai1278b112010-03-09 17:34:13 +05303385
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303386 return _scsih_check_for_pending_tm(ioc, smid);
3387}
3388
3389/**
3390 * _scsih_check_for_pending_tm - check for pending task management
3391 * @ioc: per adapter object
3392 * @smid: system request message index
3393 *
3394 * This will check delayed target reset list, and feed the
3395 * next reqeust.
3396 *
3397 * Return 1 meaning mf should be freed from _base_interrupt
3398 * 0 means the mf is freed from this function.
3399 */
3400static u8
3401_scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid)
3402{
3403 struct _tr_list *delayed_tr;
3404
3405 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3406 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3407 struct _tr_list, list);
3408 mpt2sas_base_free_smid(ioc, smid);
3409 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3410 list_del(&delayed_tr->list);
3411 kfree(delayed_tr);
3412 return 0;
3413 }
3414
Kashyap, Desai1278b112010-03-09 17:34:13 +05303415 if (!list_empty(&ioc->delayed_tr_list)) {
3416 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3417 struct _tr_list, list);
3418 mpt2sas_base_free_smid(ioc, smid);
3419 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3420 list_del(&delayed_tr->list);
3421 kfree(delayed_tr);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303422 return 0;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303423 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303424
Kashyap, Desai1278b112010-03-09 17:34:13 +05303425 return 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303426}
3427
3428/**
Eric Moore635374e2009-03-09 01:21:12 -06003429 * _scsih_check_topo_delete_events - sanity check on topo events
3430 * @ioc: per adapter object
3431 * @event_data: the event data payload
3432 *
3433 * This routine added to better handle cable breaker.
3434 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003435 * This handles the case where driver receives multiple expander
Eric Moore635374e2009-03-09 01:21:12 -06003436 * add and delete events in a single shot. When there is a delete event
3437 * the routine will void any pending add events waiting in the event queue.
3438 *
3439 * Return nothing.
3440 */
3441static void
3442_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
3443 Mpi2EventDataSasTopologyChangeList_t *event_data)
3444{
3445 struct fw_event_work *fw_event;
3446 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3447 u16 expander_handle;
3448 struct _sas_node *sas_expander;
3449 unsigned long flags;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303450 int i, reason_code;
3451 u16 handle;
3452
3453 for (i = 0 ; i < event_data->NumEntries; i++) {
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303454 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3455 if (!handle)
3456 continue;
3457 reason_code = event_data->PHY[i].PhyStatus &
3458 MPI2_EVENT_SAS_TOPO_RC_MASK;
3459 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3460 _scsih_tm_tr_send(ioc, handle);
3461 }
Eric Moore635374e2009-03-09 01:21:12 -06003462
3463 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3464 if (expander_handle < ioc->sas_hba.num_phys) {
3465 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3466 return;
3467 }
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05303468 if (event_data->ExpStatus ==
3469 MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
3470 /* put expander attached devices into blocking state */
Eric Moore635374e2009-03-09 01:21:12 -06003471 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3472 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
3473 expander_handle);
Eric Moore635374e2009-03-09 01:21:12 -06003474 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05303475 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3476 do {
3477 handle = find_first_bit(ioc->blocking_handles,
3478 ioc->facts.MaxDevHandle);
3479 if (handle < ioc->facts.MaxDevHandle)
3480 _scsih_block_io_device(ioc, handle);
3481 } while (test_and_clear_bit(handle, ioc->blocking_handles));
Eric Moore635374e2009-03-09 01:21:12 -06003482 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3483 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3484
3485 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3486 return;
3487
3488 /* mark ignore flag for pending events */
3489 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3490 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3491 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3492 fw_event->ignore)
3493 continue;
3494 local_event_data = fw_event->event_data;
3495 if (local_event_data->ExpStatus ==
3496 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3497 local_event_data->ExpStatus ==
3498 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3499 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3500 expander_handle) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303501 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06003502 "setting ignoring flag\n", ioc->name));
3503 fw_event->ignore = 1;
3504 }
3505 }
3506 }
3507 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3508}
3509
3510/**
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303511 * _scsih_set_volume_delete_flag - setting volume delete flag
3512 * @ioc: per adapter object
3513 * @handle: device handle
3514 *
3515 * This
3516 * Return nothing.
3517 */
3518static void
3519_scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3520{
3521 struct _raid_device *raid_device;
3522 struct MPT2SAS_TARGET *sas_target_priv_data;
3523 unsigned long flags;
3524
3525 spin_lock_irqsave(&ioc->raid_device_lock, flags);
3526 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
3527 if (raid_device && raid_device->starget &&
3528 raid_device->starget->hostdata) {
3529 sas_target_priv_data =
3530 raid_device->starget->hostdata;
3531 sas_target_priv_data->deleted = 1;
3532 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3533 "setting delete flag: handle(0x%04x), "
3534 "wwid(0x%016llx)\n", ioc->name, handle,
3535 (unsigned long long) raid_device->wwid));
3536 }
3537 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3538}
3539
3540/**
3541 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3542 * @handle: input handle
3543 * @a: handle for volume a
3544 * @b: handle for volume b
3545 *
3546 * IR firmware only supports two raid volumes. The purpose of this
3547 * routine is to set the volume handle in either a or b. When the given
3548 * input handle is non-zero, or when a and b have not been set before.
3549 */
3550static void
3551_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3552{
3553 if (!handle || handle == *a || handle == *b)
3554 return;
3555 if (!*a)
3556 *a = handle;
3557 else if (!*b)
3558 *b = handle;
3559}
3560
3561/**
3562 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3563 * @ioc: per adapter object
3564 * @event_data: the event data payload
3565 * Context: interrupt time.
3566 *
3567 * This routine will send target reset to volume, followed by target
3568 * resets to the PDs. This is called when a PD has been removed, or
3569 * volume has been deleted or removed. When the target reset is sent
3570 * to volume, the PD target resets need to be queued to start upon
3571 * completion of the volume target reset.
3572 *
3573 * Return nothing.
3574 */
3575static void
3576_scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc,
3577 Mpi2EventDataIrConfigChangeList_t *event_data)
3578{
3579 Mpi2EventIrConfigElement_t *element;
3580 int i;
3581 u16 handle, volume_handle, a, b;
3582 struct _tr_list *delayed_tr;
3583
3584 a = 0;
3585 b = 0;
3586
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303587 if (ioc->is_warpdrive)
3588 return;
3589
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303590 /* Volume Resets for Deleted or Removed */
3591 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3592 for (i = 0; i < event_data->NumElements; i++, element++) {
3593 if (element->ReasonCode ==
3594 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3595 element->ReasonCode ==
3596 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3597 volume_handle = le16_to_cpu(element->VolDevHandle);
3598 _scsih_set_volume_delete_flag(ioc, volume_handle);
3599 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3600 }
3601 }
3602
3603 /* Volume Resets for UNHIDE events */
3604 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3605 for (i = 0; i < event_data->NumElements; i++, element++) {
3606 if (le32_to_cpu(event_data->Flags) &
3607 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3608 continue;
3609 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3610 volume_handle = le16_to_cpu(element->VolDevHandle);
3611 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3612 }
3613 }
3614
3615 if (a)
3616 _scsih_tm_tr_volume_send(ioc, a);
3617 if (b)
3618 _scsih_tm_tr_volume_send(ioc, b);
3619
3620 /* PD target resets */
3621 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3622 for (i = 0; i < event_data->NumElements; i++, element++) {
3623 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3624 continue;
3625 handle = le16_to_cpu(element->PhysDiskDevHandle);
3626 volume_handle = le16_to_cpu(element->VolDevHandle);
3627 clear_bit(handle, ioc->pd_handles);
3628 if (!volume_handle)
3629 _scsih_tm_tr_send(ioc, handle);
3630 else if (volume_handle == a || volume_handle == b) {
3631 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3632 BUG_ON(!delayed_tr);
3633 INIT_LIST_HEAD(&delayed_tr->list);
3634 delayed_tr->handle = handle;
3635 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3636 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3637 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3638 handle));
3639 } else
3640 _scsih_tm_tr_send(ioc, handle);
3641 }
3642}
3643
3644
3645/**
3646 * _scsih_check_volume_delete_events - set delete flag for volumes
3647 * @ioc: per adapter object
3648 * @event_data: the event data payload
3649 * Context: interrupt time.
3650 *
3651 * This will handle the case when the cable connected to entire volume is
3652 * pulled. We will take care of setting the deleted flag so normal IO will
3653 * not be sent.
3654 *
3655 * Return nothing.
3656 */
3657static void
3658_scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc,
3659 Mpi2EventDataIrVolume_t *event_data)
3660{
3661 u32 state;
3662
3663 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3664 return;
3665 state = le32_to_cpu(event_data->NewValue);
3666 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3667 MPI2_RAID_VOL_STATE_FAILED)
3668 _scsih_set_volume_delete_flag(ioc,
3669 le16_to_cpu(event_data->VolDevHandle));
3670}
3671
3672/**
Eric Moore635374e2009-03-09 01:21:12 -06003673 * _scsih_flush_running_cmds - completing outstanding commands.
3674 * @ioc: per adapter object
3675 *
3676 * The flushing out of all pending scmd commands following host reset,
3677 * where all IO is dropped to the floor.
3678 *
3679 * Return nothing.
3680 */
3681static void
3682_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
3683{
3684 struct scsi_cmnd *scmd;
3685 u16 smid;
3686 u16 count = 0;
3687
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303688 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
Kashyap, Desaiec07a052011-01-05 17:54:32 +05303689 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06003690 if (!scmd)
3691 continue;
3692 count++;
3693 mpt2sas_base_free_smid(ioc, smid);
3694 scsi_dma_unmap(scmd);
Eric Moore3cb54692010-07-08 14:44:34 -06003695 if (ioc->pci_error_recovery)
3696 scmd->result = DID_NO_CONNECT << 16;
3697 else
3698 scmd->result = DID_RESET << 16;
Eric Moore635374e2009-03-09 01:21:12 -06003699 scmd->scsi_done(scmd);
3700 }
3701 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n",
3702 ioc->name, count));
3703}
3704
3705/**
Eric Moore3c621b32009-05-18 12:59:41 -06003706 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3707 * @scmd: pointer to scsi command object
3708 * @mpi_request: pointer to the SCSI_IO reqest message frame
3709 *
3710 * Supporting protection 1 and 3.
3711 *
3712 * Returns nothing
3713 */
3714static void
3715_scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request)
3716{
3717 u16 eedp_flags;
3718 unsigned char prot_op = scsi_get_prot_op(scmd);
3719 unsigned char prot_type = scsi_get_prot_type(scmd);
3720
Eric Moored334aa72010-04-22 10:47:40 -06003721 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
Eric Moore3c621b32009-05-18 12:59:41 -06003722 return;
3723
3724 if (prot_op == SCSI_PROT_READ_STRIP)
3725 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3726 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3727 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3728 else
3729 return;
3730
Eric Moore3c621b32009-05-18 12:59:41 -06003731 switch (prot_type) {
3732 case SCSI_PROT_DIF_TYPE1:
Martin K. Petersen756aca72011-05-18 00:45:22 -04003733 case SCSI_PROT_DIF_TYPE2:
Eric Moore3c621b32009-05-18 12:59:41 -06003734
3735 /*
3736 * enable ref/guard checking
3737 * auto increment ref tag
3738 */
Kashyap, Desai463217b2009-10-05 15:53:06 +05303739 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
Eric Moore3c621b32009-05-18 12:59:41 -06003740 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
3741 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3742 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
3743 cpu_to_be32(scsi_get_lba(scmd));
Eric Moored334aa72010-04-22 10:47:40 -06003744 break;
Eric Moore3c621b32009-05-18 12:59:41 -06003745
Eric Moore3c621b32009-05-18 12:59:41 -06003746 case SCSI_PROT_DIF_TYPE3:
3747
3748 /*
3749 * enable guard checking
3750 */
Kashyap, Desai463217b2009-10-05 15:53:06 +05303751 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
Eric Moore3c621b32009-05-18 12:59:41 -06003752 break;
3753 }
Kashyap, Desai463217b2009-10-05 15:53:06 +05303754 mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size);
3755 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
Eric Moore3c621b32009-05-18 12:59:41 -06003756}
3757
3758/**
3759 * _scsih_eedp_error_handling - return sense code for EEDP errors
3760 * @scmd: pointer to scsi command object
3761 * @ioc_status: ioc status
3762 *
3763 * Returns nothing
3764 */
3765static void
3766_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
3767{
3768 u8 ascq;
3769 u8 sk;
3770 u8 host_byte;
3771
3772 switch (ioc_status) {
3773 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
3774 ascq = 0x01;
3775 break;
3776 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
3777 ascq = 0x02;
3778 break;
3779 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
3780 ascq = 0x03;
3781 break;
3782 default:
3783 ascq = 0x00;
3784 break;
3785 }
3786
3787 if (scmd->sc_data_direction == DMA_TO_DEVICE) {
3788 sk = ILLEGAL_REQUEST;
3789 host_byte = DID_ABORT;
3790 } else {
3791 sk = ABORTED_COMMAND;
3792 host_byte = DID_OK;
3793 }
3794
3795 scsi_build_sense_buffer(0, scmd->sense_buffer, sk, 0x10, ascq);
3796 scmd->result = DRIVER_SENSE << 24 | (host_byte << 16) |
3797 SAM_STAT_CHECK_CONDITION;
3798}
3799
3800/**
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303801 * _scsih_scsi_direct_io_get - returns direct io flag
3802 * @ioc: per adapter object
3803 * @smid: system request message index
3804 *
3805 * Returns the smid stored scmd pointer.
3806 */
3807static inline u8
3808_scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
3809{
3810 return ioc->scsi_lookup[smid - 1].direct_io;
3811}
3812
3813/**
3814 * _scsih_scsi_direct_io_set - sets direct io flag
3815 * @ioc: per adapter object
3816 * @smid: system request message index
3817 * @direct_io: Zero or non-zero value to set in the direct_io flag
3818 *
3819 * Returns Nothing.
3820 */
3821static inline void
3822_scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
3823{
3824 ioc->scsi_lookup[smid - 1].direct_io = direct_io;
3825}
3826
3827
3828/**
3829 * _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
3830 * @ioc: per adapter object
3831 * @scmd: pointer to scsi command object
3832 * @raid_device: pointer to raid device data structure
3833 * @mpi_request: pointer to the SCSI_IO reqest message frame
3834 * @smid: system request message index
3835 *
3836 * Returns nothing
3837 */
3838static void
3839_scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3840 struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
3841 u16 smid)
3842{
3843 u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size;
3844 u32 stripe_sz, stripe_exp;
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05303845 u8 num_pds, *cdb_ptr, i;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303846 u8 cdb0 = scmd->cmnd[0];
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05303847 u64 v_llba;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303848
3849 /*
3850 * Try Direct I/O to RAID memeber disks
3851 */
3852 if (cdb0 == READ_16 || cdb0 == READ_10 ||
3853 cdb0 == WRITE_16 || cdb0 == WRITE_10) {
3854 cdb_ptr = mpi_request->CDB.CDB32;
3855
3856 if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4]
3857 | cdb_ptr[5])) {
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05303858 io_size = scsi_bufflen(scmd) >>
3859 raid_device->block_exponent;
3860 i = (cdb0 < READ_16) ? 2 : 6;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303861 /* get virtual lba */
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05303862 v_lba = be32_to_cpu(*(__be32 *)(&cdb_ptr[i]));
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303863
3864 if (((u64)v_lba + (u64)io_size - 1) <=
3865 (u32)raid_device->max_lba) {
3866 stripe_sz = raid_device->stripe_sz;
3867 stripe_exp = raid_device->stripe_exponent;
3868 stripe_off = v_lba & (stripe_sz - 1);
3869
3870 /* Check whether IO falls within a stripe */
3871 if ((stripe_off + io_size) <= stripe_sz) {
3872 num_pds = raid_device->num_pds;
3873 p_lba = v_lba >> stripe_exp;
3874 stripe_unit = p_lba / num_pds;
3875 column = p_lba % num_pds;
3876 p_lba = (stripe_unit << stripe_exp) +
3877 stripe_off;
3878 mpi_request->DevHandle =
3879 cpu_to_le16(raid_device->
3880 pd_handle[column]);
nagalakshmi.nandigama@lsi.comba96bd02011-12-01 07:51:55 +05303881 (*(__be32 *)(&cdb_ptr[i])) =
3882 cpu_to_be32(p_lba);
3883 /*
3884 * WD: To indicate this I/O is directI/O
3885 */
3886 _scsih_scsi_direct_io_set(ioc, smid, 1);
3887 }
3888 }
3889 } else {
3890 io_size = scsi_bufflen(scmd) >>
3891 raid_device->block_exponent;
3892 /* get virtual lba */
3893 v_llba = be64_to_cpu(*(__be64 *)(&cdb_ptr[2]));
3894
3895 if ((v_llba + (u64)io_size - 1) <=
3896 raid_device->max_lba) {
3897 stripe_sz = raid_device->stripe_sz;
3898 stripe_exp = raid_device->stripe_exponent;
3899 stripe_off = (u32) (v_llba & (stripe_sz - 1));
3900
3901 /* Check whether IO falls within a stripe */
3902 if ((stripe_off + io_size) <= stripe_sz) {
3903 num_pds = raid_device->num_pds;
3904 p_lba = (u32)(v_llba >> stripe_exp);
3905 stripe_unit = p_lba / num_pds;
3906 column = p_lba % num_pds;
3907 p_lba = (stripe_unit << stripe_exp) +
3908 stripe_off;
3909 mpi_request->DevHandle =
3910 cpu_to_le16(raid_device->
3911 pd_handle[column]);
3912 (*(__be64 *)(&cdb_ptr[2])) =
3913 cpu_to_be64((u64)p_lba);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303914 /*
3915 * WD: To indicate this I/O is directI/O
3916 */
3917 _scsih_scsi_direct_io_set(ioc, smid, 1);
3918 }
3919 }
3920 }
3921 }
3922}
3923
3924/**
Eric Moored5d135b2009-05-18 13:02:08 -06003925 * _scsih_qcmd - main scsi request entry point
Eric Moore635374e2009-03-09 01:21:12 -06003926 * @scmd: pointer to scsi command object
3927 * @done: function pointer to be invoked on completion
3928 *
3929 * The callback index is set inside `ioc->scsi_io_cb_idx`.
3930 *
3931 * Returns 0 on success. If there's a failure, return either:
3932 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
3933 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
3934 */
3935static int
Jeff Garzikf2812332010-11-16 02:10:29 -05003936_scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
Eric Moore635374e2009-03-09 01:21:12 -06003937{
3938 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
3939 struct MPT2SAS_DEVICE *sas_device_priv_data;
3940 struct MPT2SAS_TARGET *sas_target_priv_data;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303941 struct _raid_device *raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06003942 Mpi2SCSIIORequest_t *mpi_request;
3943 u32 mpi_control;
3944 u16 smid;
Eric Moore635374e2009-03-09 01:21:12 -06003945
3946 scmd->scsi_done = done;
3947 sas_device_priv_data = scmd->device->hostdata;
Kashyap, Desai130b9582010-04-08 17:54:32 +05303948 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Eric Moore635374e2009-03-09 01:21:12 -06003949 scmd->result = DID_NO_CONNECT << 16;
3950 scmd->scsi_done(scmd);
3951 return 0;
3952 }
3953
Kashyap, Desai78215782011-06-14 10:57:08 +05303954 if (ioc->pci_error_recovery || ioc->remove_host) {
Eric Moore3cb54692010-07-08 14:44:34 -06003955 scmd->result = DID_NO_CONNECT << 16;
3956 scmd->scsi_done(scmd);
3957 return 0;
3958 }
3959
Eric Moore635374e2009-03-09 01:21:12 -06003960 sas_target_priv_data = sas_device_priv_data->sas_target;
Kashyap, Desai130b9582010-04-08 17:54:32 +05303961 /* invalid device handle */
3962 if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
Eric Moore635374e2009-03-09 01:21:12 -06003963 scmd->result = DID_NO_CONNECT << 16;
3964 scmd->scsi_done(scmd);
3965 return 0;
3966 }
3967
Kashyap, Desai130b9582010-04-08 17:54:32 +05303968 /* host recovery or link resets sent via IOCTLs */
3969 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
Eric Moore635374e2009-03-09 01:21:12 -06003970 return SCSI_MLQUEUE_HOST_BUSY;
Uwe Kleine-König65155b32010-06-11 12:17:01 +02003971 /* device busy with task management */
Kashyap, Desai130b9582010-04-08 17:54:32 +05303972 else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
3973 return SCSI_MLQUEUE_DEVICE_BUSY;
3974 /* device has been deleted */
3975 else if (sas_target_priv_data->deleted) {
3976 scmd->result = DID_NO_CONNECT << 16;
3977 scmd->scsi_done(scmd);
3978 return 0;
3979 }
Eric Moore635374e2009-03-09 01:21:12 -06003980
3981 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
3982 mpi_control = MPI2_SCSIIO_CONTROL_READ;
3983 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
3984 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
3985 else
3986 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
3987
3988 /* set tags */
3989 if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
3990 if (scmd->device->tagged_supported) {
3991 if (scmd->device->ordered_tags)
3992 mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
3993 else
3994 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
3995 } else
3996/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */
3997/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED;
3998 */
3999 mpi_control |= (0x500);
4000
4001 } else
4002 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304003 /* Make sure Device is not raid volume.
4004 * We do not expose raid functionality to upper layer for warpdrive.
4005 */
4006 if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
Eric Moored334aa72010-04-22 10:47:40 -06004007 sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
Eric Moore635374e2009-03-09 01:21:12 -06004008 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
4009
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05304010 smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
Eric Moore635374e2009-03-09 01:21:12 -06004011 if (!smid) {
4012 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
4013 ioc->name, __func__);
4014 goto out;
4015 }
4016 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
4017 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
Eric Moore3c621b32009-05-18 12:59:41 -06004018 _scsih_setup_eedp(scmd, mpi_request);
Eric Moored334aa72010-04-22 10:47:40 -06004019 if (scmd->cmd_len == 32)
4020 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
Eric Moore635374e2009-03-09 01:21:12 -06004021 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
4022 if (sas_device_priv_data->sas_target->flags &
4023 MPT_TARGET_FLAGS_RAID_COMPONENT)
4024 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
4025 else
4026 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
4027 mpi_request->DevHandle =
4028 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4029 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
4030 mpi_request->Control = cpu_to_le32(mpi_control);
4031 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
4032 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
4033 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
4034 mpi_request->SenseBufferLowAddress =
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05304035 mpt2sas_base_get_sense_buffer_dma(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06004036 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
4037 mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI +
4038 MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304039 mpi_request->VF_ID = 0; /* TODO */
4040 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06004041 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
4042 mpi_request->LUN);
4043 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4044
4045 if (!mpi_request->DataLength) {
4046 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL);
4047 } else {
4048 if (_scsih_build_scatter_gather(ioc, scmd, smid)) {
4049 mpt2sas_base_free_smid(ioc, smid);
4050 goto out;
4051 }
4052 }
4053
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304054 raid_device = sas_target_priv_data->raid_device;
4055 if (raid_device && raid_device->direct_io_enabled)
4056 _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
4057 smid);
4058
Kashyap, Desai58287fd2010-03-17 16:27:25 +05304059 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST))
4060 mpt2sas_base_put_smid_scsi_io(ioc, smid,
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304061 le16_to_cpu(mpi_request->DevHandle));
Kashyap, Desai58287fd2010-03-17 16:27:25 +05304062 else
4063 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06004064 return 0;
4065
4066 out:
4067 return SCSI_MLQUEUE_HOST_BUSY;
4068}
4069
Jeff Garzikf2812332010-11-16 02:10:29 -05004070static DEF_SCSI_QCMD(_scsih_qcmd)
4071
Eric Moore635374e2009-03-09 01:21:12 -06004072/**
4073 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
4074 * @sense_buffer: sense data returned by target
4075 * @data: normalized skey/asc/ascq
4076 *
4077 * Return nothing.
4078 */
4079static void
4080_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
4081{
4082 if ((sense_buffer[0] & 0x7F) >= 0x72) {
4083 /* descriptor format */
4084 data->skey = sense_buffer[1] & 0x0F;
4085 data->asc = sense_buffer[2];
4086 data->ascq = sense_buffer[3];
4087 } else {
4088 /* fixed format */
4089 data->skey = sense_buffer[2] & 0x0F;
4090 data->asc = sense_buffer[12];
4091 data->ascq = sense_buffer[13];
4092 }
4093}
4094
4095#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4096/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -03004097 * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request
Eric Moore635374e2009-03-09 01:21:12 -06004098 * @ioc: per adapter object
4099 * @scmd: pointer to scsi command object
4100 * @mpi_reply: reply mf payload returned from firmware
4101 *
4102 * scsi_status - SCSI Status code returned from target device
4103 * scsi_state - state info associated with SCSI_IO determined by ioc
4104 * ioc_status - ioc supplied status info
4105 *
4106 * Return nothing.
4107 */
4108static void
4109_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
4110 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
4111{
4112 u32 response_info;
4113 u8 *response_bytes;
4114 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
4115 MPI2_IOCSTATUS_MASK;
4116 u8 scsi_state = mpi_reply->SCSIState;
4117 u8 scsi_status = mpi_reply->SCSIStatus;
4118 char *desc_ioc_state = NULL;
4119 char *desc_scsi_status = NULL;
4120 char *desc_scsi_state = ioc->tmp_string;
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +05304121 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304122 struct _sas_device *sas_device = NULL;
4123 unsigned long flags;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304124 struct scsi_target *starget = scmd->device->sdev_target;
4125 struct MPT2SAS_TARGET *priv_target = starget->hostdata;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304126 char *device_str = NULL;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304127
4128 if (!priv_target)
4129 return;
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +05304130
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304131 if (ioc->hide_ir_msg)
4132 device_str = "WarpDrive";
4133 else
4134 device_str = "volume";
4135
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +05304136 if (log_info == 0x31170000)
4137 return;
Eric Moore635374e2009-03-09 01:21:12 -06004138
4139 switch (ioc_status) {
4140 case MPI2_IOCSTATUS_SUCCESS:
4141 desc_ioc_state = "success";
4142 break;
4143 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4144 desc_ioc_state = "invalid function";
4145 break;
4146 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4147 desc_ioc_state = "scsi recovered error";
4148 break;
4149 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
4150 desc_ioc_state = "scsi invalid dev handle";
4151 break;
4152 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4153 desc_ioc_state = "scsi device not there";
4154 break;
4155 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4156 desc_ioc_state = "scsi data overrun";
4157 break;
4158 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4159 desc_ioc_state = "scsi data underrun";
4160 break;
4161 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4162 desc_ioc_state = "scsi io data error";
4163 break;
4164 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4165 desc_ioc_state = "scsi protocol error";
4166 break;
4167 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4168 desc_ioc_state = "scsi task terminated";
4169 break;
4170 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4171 desc_ioc_state = "scsi residual mismatch";
4172 break;
4173 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4174 desc_ioc_state = "scsi task mgmt failed";
4175 break;
4176 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4177 desc_ioc_state = "scsi ioc terminated";
4178 break;
4179 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4180 desc_ioc_state = "scsi ext terminated";
4181 break;
Eric Moore3c621b32009-05-18 12:59:41 -06004182 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4183 desc_ioc_state = "eedp guard error";
4184 break;
4185 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4186 desc_ioc_state = "eedp ref tag error";
4187 break;
4188 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4189 desc_ioc_state = "eedp app tag error";
4190 break;
Eric Moore635374e2009-03-09 01:21:12 -06004191 default:
4192 desc_ioc_state = "unknown";
4193 break;
4194 }
4195
4196 switch (scsi_status) {
4197 case MPI2_SCSI_STATUS_GOOD:
4198 desc_scsi_status = "good";
4199 break;
4200 case MPI2_SCSI_STATUS_CHECK_CONDITION:
4201 desc_scsi_status = "check condition";
4202 break;
4203 case MPI2_SCSI_STATUS_CONDITION_MET:
4204 desc_scsi_status = "condition met";
4205 break;
4206 case MPI2_SCSI_STATUS_BUSY:
4207 desc_scsi_status = "busy";
4208 break;
4209 case MPI2_SCSI_STATUS_INTERMEDIATE:
4210 desc_scsi_status = "intermediate";
4211 break;
4212 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
4213 desc_scsi_status = "intermediate condmet";
4214 break;
4215 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
4216 desc_scsi_status = "reservation conflict";
4217 break;
4218 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
4219 desc_scsi_status = "command terminated";
4220 break;
4221 case MPI2_SCSI_STATUS_TASK_SET_FULL:
4222 desc_scsi_status = "task set full";
4223 break;
4224 case MPI2_SCSI_STATUS_ACA_ACTIVE:
4225 desc_scsi_status = "aca active";
4226 break;
4227 case MPI2_SCSI_STATUS_TASK_ABORTED:
4228 desc_scsi_status = "task aborted";
4229 break;
4230 default:
4231 desc_scsi_status = "unknown";
4232 break;
4233 }
4234
4235 desc_scsi_state[0] = '\0';
4236 if (!scsi_state)
4237 desc_scsi_state = " ";
4238 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4239 strcat(desc_scsi_state, "response info ");
4240 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4241 strcat(desc_scsi_state, "state terminated ");
4242 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
4243 strcat(desc_scsi_state, "no status ");
4244 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
4245 strcat(desc_scsi_state, "autosense failed ");
4246 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
4247 strcat(desc_scsi_state, "autosense valid ");
4248
4249 scsi_print_command(scmd);
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304250
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304251 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304252 printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
4253 device_str, (unsigned long long)priv_target->sas_address);
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304254 } else {
4255 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4256 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
4257 priv_target->sas_address);
4258 if (sas_device) {
4259 printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
4260 "phy(%d)\n", ioc->name, sas_device->sas_address,
4261 sas_device->phy);
4262 printk(MPT2SAS_WARN_FMT
4263 "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
4264 ioc->name, sas_device->enclosure_logical_id,
4265 sas_device->slot);
4266 }
4267 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304268 }
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304269
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304270 printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), "
4271 "smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle),
4272 desc_ioc_state, ioc_status, smid);
Eric Moore635374e2009-03-09 01:21:12 -06004273 printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), "
4274 "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow,
4275 scsi_get_resid(scmd));
4276 printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), "
4277 "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag),
4278 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
4279 printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), "
4280 "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status,
4281 scsi_status, desc_scsi_state, scsi_state);
4282
4283 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4284 struct sense_info data;
4285 _scsih_normalize_sense(scmd->sense_buffer, &data);
4286 printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: "
Kashyap, Desaie94f6742010-03-17 16:24:52 +05304287 "[0x%02x,0x%02x,0x%02x], count(%d)\n", ioc->name, data.skey,
4288 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
Eric Moore635374e2009-03-09 01:21:12 -06004289 }
4290
4291 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
4292 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
4293 response_bytes = (u8 *)&response_info;
Kashyap, Desai9982f592009-09-23 17:23:07 +05304294 _scsih_response_code(ioc, response_bytes[0]);
Eric Moore635374e2009-03-09 01:21:12 -06004295 }
4296}
4297#endif
4298
4299/**
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05304300 * _scsih_turn_on_fault_led - illuminate Fault LED
Eric Moore635374e2009-03-09 01:21:12 -06004301 * @ioc: per adapter object
4302 * @handle: device handle
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05304303 * Context: process
4304 *
4305 * Return nothing.
4306 */
4307static void
4308_scsih_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4309{
4310 Mpi2SepReply_t mpi_reply;
4311 Mpi2SepRequest_t mpi_request;
4312
4313 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4314 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4315 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4316 mpi_request.SlotStatus =
4317 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
4318 mpi_request.DevHandle = cpu_to_le16(handle);
4319 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
4320 if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4321 &mpi_request)) != 0) {
4322 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
4323 __FILE__, __LINE__, __func__);
4324 return;
4325 }
4326
4327 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4328 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: "
4329 "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name,
4330 le16_to_cpu(mpi_reply.IOCStatus),
4331 le32_to_cpu(mpi_reply.IOCLogInfo)));
4332 return;
4333 }
4334}
4335
4336/**
4337 * _scsih_send_event_to_turn_on_fault_led - fire delayed event
4338 * @ioc: per adapter object
4339 * @handle: device handle
4340 * Context: interrupt.
4341 *
4342 * Return nothing.
4343 */
4344static void
4345_scsih_send_event_to_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4346{
4347 struct fw_event_work *fw_event;
4348
4349 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
4350 if (!fw_event)
4351 return;
4352 fw_event->event = MPT2SAS_TURN_ON_FAULT_LED;
4353 fw_event->device_handle = handle;
4354 fw_event->ioc = ioc;
4355 _scsih_fw_event_add(ioc, fw_event);
4356}
4357
4358/**
4359 * _scsih_smart_predicted_fault - process smart errors
4360 * @ioc: per adapter object
4361 * @handle: device handle
4362 * Context: interrupt.
Eric Moore635374e2009-03-09 01:21:12 -06004363 *
4364 * Return nothing.
4365 */
4366static void
4367_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4368{
Eric Moore635374e2009-03-09 01:21:12 -06004369 struct scsi_target *starget;
4370 struct MPT2SAS_TARGET *sas_target_priv_data;
4371 Mpi2EventNotificationReply_t *event_reply;
4372 Mpi2EventDataSasDeviceStatusChange_t *event_data;
4373 struct _sas_device *sas_device;
4374 ssize_t sz;
4375 unsigned long flags;
4376
4377 /* only handle non-raid devices */
4378 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4379 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4380 if (!sas_device) {
4381 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4382 return;
4383 }
4384 starget = sas_device->starget;
4385 sas_target_priv_data = starget->hostdata;
4386
4387 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
4388 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
4389 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4390 return;
4391 }
4392 starget_printk(KERN_WARNING, starget, "predicted fault\n");
4393 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4394
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05304395 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
4396 _scsih_send_event_to_turn_on_fault_led(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06004397
4398 /* insert into event log */
4399 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
4400 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
Anton Blanchardf6a290b42011-11-07 22:05:21 +11004401 event_reply = kzalloc(sz, GFP_ATOMIC);
Eric Moore635374e2009-03-09 01:21:12 -06004402 if (!event_reply) {
4403 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4404 ioc->name, __FILE__, __LINE__, __func__);
4405 return;
4406 }
4407
4408 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
4409 event_reply->Event =
4410 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4411 event_reply->MsgLength = sz/4;
4412 event_reply->EventDataLength =
4413 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
4414 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
4415 event_reply->EventData;
4416 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4417 event_data->ASC = 0x5D;
4418 event_data->DevHandle = cpu_to_le16(handle);
4419 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4420 mpt2sas_ctl_add_to_event_log(ioc, event_reply);
4421 kfree(event_reply);
4422}
4423
4424/**
Eric Moored5d135b2009-05-18 13:02:08 -06004425 * _scsih_io_done - scsi request callback
Eric Moore635374e2009-03-09 01:21:12 -06004426 * @ioc: per adapter object
4427 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304428 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -06004429 * @reply: reply message frame(lower 32bit addr)
4430 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304431 * Callback handler when using _scsih_qcmd.
Eric Moore635374e2009-03-09 01:21:12 -06004432 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304433 * Return 1 meaning mf should be freed from _base_interrupt
4434 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -06004435 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304436static u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304437_scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -06004438{
4439 Mpi2SCSIIORequest_t *mpi_request;
4440 Mpi2SCSIIOReply_t *mpi_reply;
4441 struct scsi_cmnd *scmd;
4442 u16 ioc_status;
4443 u32 xfer_cnt;
4444 u8 scsi_state;
4445 u8 scsi_status;
4446 u32 log_info;
4447 struct MPT2SAS_DEVICE *sas_device_priv_data;
Kashyap, Desai9982f592009-09-23 17:23:07 +05304448 u32 response_code = 0;
Kashyap, Desai82a45252011-07-05 12:40:23 +05304449 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06004450
4451 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
Kashyap, Desaiec07a052011-01-05 17:54:32 +05304452 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06004453 if (scmd == NULL)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304454 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06004455
4456 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
4457
4458 if (mpi_reply == NULL) {
4459 scmd->result = DID_OK << 16;
4460 goto out;
4461 }
4462
4463 sas_device_priv_data = scmd->device->hostdata;
4464 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4465 sas_device_priv_data->sas_target->deleted) {
4466 scmd->result = DID_NO_CONNECT << 16;
4467 goto out;
4468 }
nagalakshmi.nandigama@lsi.com4da7af92011-12-01 07:53:02 +05304469 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304470 /*
4471 * WARPDRIVE: If direct_io is set then it is directIO,
4472 * the failed direct I/O should be redirected to volume
4473 */
nagalakshmi.nandigama@lsi.com4da7af92011-12-01 07:53:02 +05304474 if (_scsih_scsi_direct_io_get(ioc, smid) &&
4475 ((ioc_status & MPI2_IOCSTATUS_MASK)
4476 != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
Kashyap, Desai82a45252011-07-05 12:40:23 +05304477 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4478 ioc->scsi_lookup[smid - 1].scmd = scmd;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304479 _scsih_scsi_direct_io_set(ioc, smid, 0);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05304480 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304481 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4482 mpi_request->DevHandle =
4483 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4484 mpt2sas_base_put_smid_scsi_io(ioc, smid,
4485 sas_device_priv_data->sas_target->handle);
4486 return 0;
4487 }
4488
Eric Moore635374e2009-03-09 01:21:12 -06004489
4490 /* turning off TLR */
Kashyap, Desai9982f592009-09-23 17:23:07 +05304491 scsi_state = mpi_reply->SCSIState;
4492 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4493 response_code =
4494 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
Eric Moore635374e2009-03-09 01:21:12 -06004495 if (!sas_device_priv_data->tlr_snoop_check) {
4496 sas_device_priv_data->tlr_snoop_check++;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304497 /* Make sure Device is not raid volume.
4498 * We do not expose raid functionality to upper layer for warpdrive.
4499 */
4500 if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
Kashyap, Desai3ed21522010-02-17 16:08:36 +05304501 sas_is_tlr_enabled(scmd->device) &&
Kashyap, Desai84f0b042009-12-16 18:56:28 +05304502 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
4503 sas_disable_tlr(scmd->device);
4504 sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
4505 }
Eric Moore635374e2009-03-09 01:21:12 -06004506 }
4507
4508 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
4509 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
Eric Moore635374e2009-03-09 01:21:12 -06004510 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4511 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4512 else
4513 log_info = 0;
4514 ioc_status &= MPI2_IOCSTATUS_MASK;
Eric Moore635374e2009-03-09 01:21:12 -06004515 scsi_status = mpi_reply->SCSIStatus;
4516
4517 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4518 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4519 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4520 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4521 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4522 }
4523
4524 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4525 struct sense_info data;
4526 const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
4527 smid);
Eric Moore0d04df92009-04-21 15:38:43 -06004528 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
Eric Moore635374e2009-03-09 01:21:12 -06004529 le32_to_cpu(mpi_reply->SenseCount));
Eric Moore0d04df92009-04-21 15:38:43 -06004530 memcpy(scmd->sense_buffer, sense_data, sz);
Eric Moore635374e2009-03-09 01:21:12 -06004531 _scsih_normalize_sense(scmd->sense_buffer, &data);
4532 /* failure prediction threshold exceeded */
4533 if (data.asc == 0x5D)
4534 _scsih_smart_predicted_fault(ioc,
4535 le16_to_cpu(mpi_reply->DevHandle));
4536 }
4537
4538 switch (ioc_status) {
4539 case MPI2_IOCSTATUS_BUSY:
4540 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4541 scmd->result = SAM_STAT_BUSY;
4542 break;
4543
4544 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4545 scmd->result = DID_NO_CONNECT << 16;
4546 break;
4547
4548 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4549 if (sas_device_priv_data->block) {
Kashyap, Desaie4e7c7e2009-09-23 17:33:14 +05304550 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4551 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06004552 }
nagalakshmi.nandigama@lsi.com3ade1ca2011-12-01 07:42:40 +05304553 scmd->result = DID_SOFT_ERROR << 16;
4554 break;
Eric Moore635374e2009-03-09 01:21:12 -06004555 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4556 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4557 scmd->result = DID_RESET << 16;
4558 break;
4559
4560 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4561 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4562 scmd->result = DID_SOFT_ERROR << 16;
4563 else
4564 scmd->result = (DID_OK << 16) | scsi_status;
4565 break;
4566
4567 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4568 scmd->result = (DID_OK << 16) | scsi_status;
4569
4570 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4571 break;
4572
4573 if (xfer_cnt < scmd->underflow) {
4574 if (scsi_status == SAM_STAT_BUSY)
4575 scmd->result = SAM_STAT_BUSY;
4576 else
4577 scmd->result = DID_SOFT_ERROR << 16;
4578 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4579 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4580 scmd->result = DID_SOFT_ERROR << 16;
4581 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4582 scmd->result = DID_RESET << 16;
4583 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4584 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4585 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4586 scmd->result = (DRIVER_SENSE << 24) |
4587 SAM_STAT_CHECK_CONDITION;
4588 scmd->sense_buffer[0] = 0x70;
4589 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4590 scmd->sense_buffer[12] = 0x20;
4591 scmd->sense_buffer[13] = 0;
4592 }
4593 break;
4594
4595 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4596 scsi_set_resid(scmd, 0);
4597 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4598 case MPI2_IOCSTATUS_SUCCESS:
4599 scmd->result = (DID_OK << 16) | scsi_status;
Kashyap, Desai9982f592009-09-23 17:23:07 +05304600 if (response_code ==
4601 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4602 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4603 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
Eric Moore635374e2009-03-09 01:21:12 -06004604 scmd->result = DID_SOFT_ERROR << 16;
4605 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4606 scmd->result = DID_RESET << 16;
4607 break;
4608
Eric Moore3c621b32009-05-18 12:59:41 -06004609 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4610 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4611 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4612 _scsih_eedp_error_handling(scmd, ioc_status);
4613 break;
Eric Moore635374e2009-03-09 01:21:12 -06004614 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4615 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4616 case MPI2_IOCSTATUS_INVALID_SGL:
4617 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4618 case MPI2_IOCSTATUS_INVALID_FIELD:
4619 case MPI2_IOCSTATUS_INVALID_STATE:
4620 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4621 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4622 default:
4623 scmd->result = DID_SOFT_ERROR << 16;
4624 break;
4625
4626 }
4627
4628#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4629 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4630 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
4631#endif
4632
4633 out:
4634 scsi_dma_unmap(scmd);
4635 scmd->scsi_done(scmd);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304636 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06004637}
4638
4639/**
Eric Moore635374e2009-03-09 01:21:12 -06004640 * _scsih_sas_host_refresh - refreshing sas host object contents
4641 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06004642 * Context: user
4643 *
4644 * During port enable, fw will send topology events for every device. Its
4645 * possible that the handles may change from the previous setting, so this
4646 * code keeping handles updating if changed.
4647 *
4648 * Return nothing.
4649 */
4650static void
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304651_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
Eric Moore635374e2009-03-09 01:21:12 -06004652{
4653 u16 sz;
4654 u16 ioc_status;
4655 int i;
4656 Mpi2ConfigReply_t mpi_reply;
4657 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304658 u16 attached_handle;
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304659 u8 link_rate;
Eric Moore635374e2009-03-09 01:21:12 -06004660
4661 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
4662 "updating handles for sas_host(0x%016llx)\n",
4663 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4664
4665 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4666 * sizeof(Mpi2SasIOUnit0PhyData_t));
4667 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4668 if (!sas_iounit_pg0) {
4669 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4670 ioc->name, __FILE__, __LINE__, __func__);
4671 return;
4672 }
Eric Moore635374e2009-03-09 01:21:12 -06004673
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304674 if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4675 sas_iounit_pg0, sz)) != 0)
4676 goto out;
4677 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4678 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4679 goto out;
4680 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304681 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304682 if (i == 0)
4683 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4684 PhyData[0].ControllerDevHandle);
4685 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4686 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4687 AttachedDevHandle);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304688 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4689 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304690 mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304691 attached_handle, i, link_rate);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304692 }
Eric Moore635374e2009-03-09 01:21:12 -06004693 out:
4694 kfree(sas_iounit_pg0);
4695}
4696
4697/**
4698 * _scsih_sas_host_add - create sas host object
4699 * @ioc: per adapter object
4700 *
4701 * Creating host side data object, stored in ioc->sas_hba
4702 *
4703 * Return nothing.
4704 */
4705static void
4706_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
4707{
4708 int i;
4709 Mpi2ConfigReply_t mpi_reply;
4710 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4711 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4712 Mpi2SasPhyPage0_t phy_pg0;
4713 Mpi2SasDevicePage0_t sas_device_pg0;
4714 Mpi2SasEnclosurePage0_t enclosure_pg0;
4715 u16 ioc_status;
4716 u16 sz;
4717 u16 device_missing_delay;
4718
4719 mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
4720 if (!ioc->sas_hba.num_phys) {
4721 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4722 ioc->name, __FILE__, __LINE__, __func__);
4723 return;
4724 }
4725
4726 /* sas_iounit page 0 */
4727 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
4728 sizeof(Mpi2SasIOUnit0PhyData_t));
4729 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4730 if (!sas_iounit_pg0) {
4731 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4732 ioc->name, __FILE__, __LINE__, __func__);
4733 return;
4734 }
4735 if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4736 sas_iounit_pg0, sz))) {
4737 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4738 ioc->name, __FILE__, __LINE__, __func__);
4739 goto out;
4740 }
4741 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4742 MPI2_IOCSTATUS_MASK;
4743 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4744 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4745 ioc->name, __FILE__, __LINE__, __func__);
4746 goto out;
4747 }
4748
4749 /* sas_iounit page 1 */
4750 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
4751 sizeof(Mpi2SasIOUnit1PhyData_t));
4752 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
4753 if (!sas_iounit_pg1) {
4754 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4755 ioc->name, __FILE__, __LINE__, __func__);
4756 goto out;
4757 }
4758 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
4759 sas_iounit_pg1, sz))) {
4760 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4761 ioc->name, __FILE__, __LINE__, __func__);
4762 goto out;
4763 }
4764 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4765 MPI2_IOCSTATUS_MASK;
4766 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4767 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4768 ioc->name, __FILE__, __LINE__, __func__);
4769 goto out;
4770 }
4771
4772 ioc->io_missing_delay =
4773 le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay);
4774 device_missing_delay =
4775 le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay);
4776 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
4777 ioc->device_missing_delay = (device_missing_delay &
4778 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
4779 else
4780 ioc->device_missing_delay = device_missing_delay &
4781 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
4782
4783 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
4784 ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
4785 sizeof(struct _sas_phy), GFP_KERNEL);
4786 if (!ioc->sas_hba.phy) {
4787 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4788 ioc->name, __FILE__, __LINE__, __func__);
4789 goto out;
4790 }
4791 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4792 if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
4793 i))) {
4794 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4795 ioc->name, __FILE__, __LINE__, __func__);
4796 goto out;
4797 }
4798 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4799 MPI2_IOCSTATUS_MASK;
4800 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4801 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4802 ioc->name, __FILE__, __LINE__, __func__);
4803 goto out;
4804 }
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304805
4806 if (i == 0)
4807 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4808 PhyData[0].ControllerDevHandle);
4809 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
Eric Moore635374e2009-03-09 01:21:12 -06004810 ioc->sas_hba.phy[i].phy_id = i;
4811 mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
4812 phy_pg0, ioc->sas_hba.parent_dev);
4813 }
4814 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304815 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
Eric Moore635374e2009-03-09 01:21:12 -06004816 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4817 ioc->name, __FILE__, __LINE__, __func__);
4818 goto out;
4819 }
Eric Moore635374e2009-03-09 01:21:12 -06004820 ioc->sas_hba.enclosure_handle =
4821 le16_to_cpu(sas_device_pg0.EnclosureHandle);
4822 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4823 printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), "
4824 "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle,
4825 (unsigned long long) ioc->sas_hba.sas_address,
4826 ioc->sas_hba.num_phys) ;
4827
4828 if (ioc->sas_hba.enclosure_handle) {
4829 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4830 &enclosure_pg0,
4831 MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4832 ioc->sas_hba.enclosure_handle))) {
4833 ioc->sas_hba.enclosure_logical_id =
4834 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4835 }
4836 }
4837
4838 out:
4839 kfree(sas_iounit_pg1);
4840 kfree(sas_iounit_pg0);
4841}
4842
4843/**
4844 * _scsih_expander_add - creating expander object
4845 * @ioc: per adapter object
4846 * @handle: expander handle
4847 *
4848 * Creating expander object, stored in ioc->sas_expander_list.
4849 *
4850 * Return 0 for success, else error.
4851 */
4852static int
4853_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4854{
4855 struct _sas_node *sas_expander;
4856 Mpi2ConfigReply_t mpi_reply;
4857 Mpi2ExpanderPage0_t expander_pg0;
4858 Mpi2ExpanderPage1_t expander_pg1;
4859 Mpi2SasEnclosurePage0_t enclosure_pg0;
4860 u32 ioc_status;
4861 u16 parent_handle;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05304862 u64 sas_address, sas_address_parent = 0;
Eric Moore635374e2009-03-09 01:21:12 -06004863 int i;
4864 unsigned long flags;
Kashyap, Desai20f58952009-08-07 19:34:26 +05304865 struct _sas_port *mpt2sas_port = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06004866 int rc = 0;
4867
4868 if (!handle)
4869 return -1;
4870
Eric Moore3cb54692010-07-08 14:44:34 -06004871 if (ioc->shost_recovery || ioc->pci_error_recovery)
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05304872 return -1;
4873
Eric Moore635374e2009-03-09 01:21:12 -06004874 if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
4875 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
4876 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4877 ioc->name, __FILE__, __LINE__, __func__);
4878 return -1;
4879 }
4880
4881 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4882 MPI2_IOCSTATUS_MASK;
4883 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4884 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4885 ioc->name, __FILE__, __LINE__, __func__);
4886 return -1;
4887 }
4888
4889 /* handle out of order topology events */
4890 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304891 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
4892 != 0) {
4893 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4894 ioc->name, __FILE__, __LINE__, __func__);
4895 return -1;
4896 }
4897 if (sas_address_parent != ioc->sas_hba.sas_address) {
Eric Moore635374e2009-03-09 01:21:12 -06004898 spin_lock_irqsave(&ioc->sas_node_lock, flags);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304899 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
4900 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06004901 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4902 if (!sas_expander) {
4903 rc = _scsih_expander_add(ioc, parent_handle);
4904 if (rc != 0)
4905 return rc;
4906 }
4907 }
4908
Eric Moore635374e2009-03-09 01:21:12 -06004909 spin_lock_irqsave(&ioc->sas_node_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05304910 sas_address = le64_to_cpu(expander_pg0.SASAddress);
Eric Moore635374e2009-03-09 01:21:12 -06004911 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
4912 sas_address);
4913 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4914
4915 if (sas_expander)
4916 return 0;
4917
4918 sas_expander = kzalloc(sizeof(struct _sas_node),
4919 GFP_KERNEL);
4920 if (!sas_expander) {
4921 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4922 ioc->name, __FILE__, __LINE__, __func__);
4923 return -1;
4924 }
4925
4926 sas_expander->handle = handle;
4927 sas_expander->num_phys = expander_pg0.NumPhys;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304928 sas_expander->sas_address_parent = sas_address_parent;
Eric Moore635374e2009-03-09 01:21:12 -06004929 sas_expander->sas_address = sas_address;
4930
4931 printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
4932 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304933 handle, parent_handle, (unsigned long long)
Eric Moore635374e2009-03-09 01:21:12 -06004934 sas_expander->sas_address, sas_expander->num_phys);
4935
4936 if (!sas_expander->num_phys)
4937 goto out_fail;
4938 sas_expander->phy = kcalloc(sas_expander->num_phys,
4939 sizeof(struct _sas_phy), GFP_KERNEL);
4940 if (!sas_expander->phy) {
4941 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4942 ioc->name, __FILE__, __LINE__, __func__);
4943 rc = -1;
4944 goto out_fail;
4945 }
4946
4947 INIT_LIST_HEAD(&sas_expander->sas_port_list);
4948 mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304949 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06004950 if (!mpt2sas_port) {
4951 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4952 ioc->name, __FILE__, __LINE__, __func__);
4953 rc = -1;
4954 goto out_fail;
4955 }
4956 sas_expander->parent_dev = &mpt2sas_port->rphy->dev;
4957
4958 for (i = 0 ; i < sas_expander->num_phys ; i++) {
4959 if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
4960 &expander_pg1, i, handle))) {
4961 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4962 ioc->name, __FILE__, __LINE__, __func__);
Kashyap, Desai20f58952009-08-07 19:34:26 +05304963 rc = -1;
4964 goto out_fail;
Eric Moore635374e2009-03-09 01:21:12 -06004965 }
4966 sas_expander->phy[i].handle = handle;
4967 sas_expander->phy[i].phy_id = i;
Kashyap, Desai20f58952009-08-07 19:34:26 +05304968
4969 if ((mpt2sas_transport_add_expander_phy(ioc,
4970 &sas_expander->phy[i], expander_pg1,
4971 sas_expander->parent_dev))) {
4972 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4973 ioc->name, __FILE__, __LINE__, __func__);
4974 rc = -1;
4975 goto out_fail;
4976 }
Eric Moore635374e2009-03-09 01:21:12 -06004977 }
4978
4979 if (sas_expander->enclosure_handle) {
4980 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4981 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4982 sas_expander->enclosure_handle))) {
4983 sas_expander->enclosure_logical_id =
4984 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4985 }
4986 }
4987
4988 _scsih_expander_node_add(ioc, sas_expander);
4989 return 0;
4990
4991 out_fail:
4992
Kashyap, Desai20f58952009-08-07 19:34:26 +05304993 if (mpt2sas_port)
4994 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304995 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06004996 kfree(sas_expander);
4997 return rc;
4998}
4999
5000/**
Kashyap, Desai744090d2009-10-05 15:56:56 +05305001 * _scsih_done - scsih callback handler.
5002 * @ioc: per adapter object
5003 * @smid: system request message index
5004 * @msix_index: MSIX table index supplied by the OS
5005 * @reply: reply message frame(lower 32bit addr)
5006 *
5007 * Callback handler when sending internal generated message frames.
5008 * The callback index passed is `ioc->scsih_cb_idx`
5009 *
5010 * Return 1 meaning mf should be freed from _base_interrupt
5011 * 0 means the mf is freed from this function.
5012 */
5013static u8
5014_scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
5015{
5016 MPI2DefaultReply_t *mpi_reply;
5017
5018 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
5019 if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED)
5020 return 1;
5021 if (ioc->scsih_cmds.smid != smid)
5022 return 1;
5023 ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE;
5024 if (mpi_reply) {
5025 memcpy(ioc->scsih_cmds.reply, mpi_reply,
5026 mpi_reply->MsgLength*4);
5027 ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID;
5028 }
5029 ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING;
5030 complete(&ioc->scsih_cmds.done);
5031 return 1;
5032}
5033
5034/**
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305035 * mpt2sas_expander_remove - removing expander object
Eric Moore635374e2009-03-09 01:21:12 -06005036 * @ioc: per adapter object
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305037 * @sas_address: expander sas_address
Eric Moore635374e2009-03-09 01:21:12 -06005038 *
5039 * Return nothing.
5040 */
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305041void
5042mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
Eric Moore635374e2009-03-09 01:21:12 -06005043{
5044 struct _sas_node *sas_expander;
5045 unsigned long flags;
5046
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05305047 if (ioc->shost_recovery)
5048 return;
5049
Eric Moore635374e2009-03-09 01:21:12 -06005050 spin_lock_irqsave(&ioc->sas_node_lock, flags);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305051 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
5052 sas_address);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305053 if (sas_expander)
5054 list_del(&sas_expander->list);
Eric Moore635374e2009-03-09 01:21:12 -06005055 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305056 if (sas_expander)
5057 _scsih_expander_node_remove(ioc, sas_expander);
Eric Moore635374e2009-03-09 01:21:12 -06005058}
5059
5060/**
Kashyap, Desaib4344272010-03-17 16:24:14 +05305061 * _scsih_check_access_status - check access flags
5062 * @ioc: per adapter object
5063 * @sas_address: sas address
5064 * @handle: sas device handle
5065 * @access_flags: errors returned during discovery of the device
5066 *
5067 * Return 0 for success, else failure
5068 */
5069static u8
5070_scsih_check_access_status(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
5071 u16 handle, u8 access_status)
5072{
5073 u8 rc = 1;
5074 char *desc = NULL;
5075
5076 switch (access_status) {
5077 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
5078 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
5079 rc = 0;
5080 break;
5081 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
5082 desc = "sata capability failed";
5083 break;
5084 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
5085 desc = "sata affiliation conflict";
5086 break;
5087 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
5088 desc = "route not addressable";
5089 break;
5090 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
5091 desc = "smp error not addressable";
5092 break;
5093 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
5094 desc = "device blocked";
5095 break;
5096 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
5097 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
5098 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
5099 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
5100 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
5101 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
5102 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
5103 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
5104 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
5105 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
5106 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
5107 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
5108 desc = "sata initialization failed";
5109 break;
5110 default:
5111 desc = "unknown";
5112 break;
5113 }
5114
5115 if (!rc)
5116 return 0;
5117
5118 printk(MPT2SAS_ERR_FMT "discovery errors(%s): sas_address(0x%016llx), "
5119 "handle(0x%04x)\n", ioc->name, desc,
5120 (unsigned long long)sas_address, handle);
5121 return rc;
5122}
5123
5124static void
5125_scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
5126{
5127 Mpi2ConfigReply_t mpi_reply;
5128 Mpi2SasDevicePage0_t sas_device_pg0;
5129 struct _sas_device *sas_device;
5130 u32 ioc_status;
5131 unsigned long flags;
5132 u64 sas_address;
5133 struct scsi_target *starget;
5134 struct MPT2SAS_TARGET *sas_target_priv_data;
5135 u32 device_info;
5136
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305137
Kashyap, Desaib4344272010-03-17 16:24:14 +05305138 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5139 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
5140 return;
5141
5142 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
5143 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
5144 return;
5145
5146 /* check if this is end device */
5147 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5148 if (!(_scsih_is_end_device(device_info)))
5149 return;
5150
5151 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5152 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5153 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5154 sas_address);
5155
5156 if (!sas_device) {
5157 printk(MPT2SAS_ERR_FMT "device is not present "
5158 "handle(0x%04x), no sas_device!!!\n", ioc->name, handle);
5159 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5160 return;
5161 }
5162
5163 if (unlikely(sas_device->handle != handle)) {
5164 starget = sas_device->starget;
5165 sas_target_priv_data = starget->hostdata;
5166 starget_printk(KERN_INFO, starget, "handle changed from(0x%04x)"
5167 " to (0x%04x)!!!\n", sas_device->handle, handle);
5168 sas_target_priv_data->handle = handle;
5169 sas_device->handle = handle;
5170 }
Kashyap, Desaib4344272010-03-17 16:24:14 +05305171
5172 /* check if device is present */
5173 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5174 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5175 printk(MPT2SAS_ERR_FMT "device is not present "
5176 "handle(0x%04x), flags!!!\n", ioc->name, handle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305177 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desaib4344272010-03-17 16:24:14 +05305178 return;
5179 }
5180
5181 /* check if there were any issues with discovery */
5182 if (_scsih_check_access_status(ioc, sas_address, handle,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305183 sas_device_pg0.AccessStatus)) {
5184 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desaib4344272010-03-17 16:24:14 +05305185 return;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305186 }
5187 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desaib4344272010-03-17 16:24:14 +05305188 _scsih_ublock_io_device(ioc, handle);
5189
5190}
5191
5192/**
Eric Moore635374e2009-03-09 01:21:12 -06005193 * _scsih_add_device - creating sas device object
5194 * @ioc: per adapter object
5195 * @handle: sas device handle
5196 * @phy_num: phy number end device attached to
5197 * @is_pd: is this hidden raid component
5198 *
5199 * Creating end device object, stored in ioc->sas_device_list.
5200 *
5201 * Returns 0 for success, non-zero for failure.
5202 */
5203static int
5204_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
5205{
5206 Mpi2ConfigReply_t mpi_reply;
5207 Mpi2SasDevicePage0_t sas_device_pg0;
5208 Mpi2SasEnclosurePage0_t enclosure_pg0;
5209 struct _sas_device *sas_device;
5210 u32 ioc_status;
5211 __le64 sas_address;
5212 u32 device_info;
5213 unsigned long flags;
5214
5215 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5216 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5217 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5218 ioc->name, __FILE__, __LINE__, __func__);
5219 return -1;
5220 }
5221
5222 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5223 MPI2_IOCSTATUS_MASK;
5224 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5225 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5226 ioc->name, __FILE__, __LINE__, __func__);
5227 return -1;
5228 }
5229
Kashyap, Desaib4344272010-03-17 16:24:14 +05305230 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5231
Eric Moore635374e2009-03-09 01:21:12 -06005232 /* check if device is present */
5233 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5234 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5235 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5236 ioc->name, __FILE__, __LINE__, __func__);
5237 printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n",
5238 ioc->name, le16_to_cpu(sas_device_pg0.Flags));
5239 return -1;
5240 }
5241
Kashyap, Desaib4344272010-03-17 16:24:14 +05305242 /* check if there were any issues with discovery */
5243 if (_scsih_check_access_status(ioc, sas_address, handle,
5244 sas_device_pg0.AccessStatus))
Eric Moore635374e2009-03-09 01:21:12 -06005245 return -1;
Eric Moore635374e2009-03-09 01:21:12 -06005246
5247 /* check if this is end device */
5248 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5249 if (!(_scsih_is_end_device(device_info))) {
5250 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5251 ioc->name, __FILE__, __LINE__, __func__);
5252 return -1;
5253 }
5254
Eric Moore635374e2009-03-09 01:21:12 -06005255
5256 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5257 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5258 sas_address);
5259 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5260
Kashyap, Desaib4344272010-03-17 16:24:14 +05305261 if (sas_device)
Eric Moore635374e2009-03-09 01:21:12 -06005262 return 0;
Eric Moore635374e2009-03-09 01:21:12 -06005263
5264 sas_device = kzalloc(sizeof(struct _sas_device),
5265 GFP_KERNEL);
5266 if (!sas_device) {
5267 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5268 ioc->name, __FILE__, __LINE__, __func__);
5269 return -1;
5270 }
5271
5272 sas_device->handle = handle;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305273 if (_scsih_get_sas_address(ioc, le16_to_cpu
5274 (sas_device_pg0.ParentDevHandle),
5275 &sas_device->sas_address_parent) != 0)
5276 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5277 ioc->name, __FILE__, __LINE__, __func__);
Eric Moore635374e2009-03-09 01:21:12 -06005278 sas_device->enclosure_handle =
5279 le16_to_cpu(sas_device_pg0.EnclosureHandle);
5280 sas_device->slot =
5281 le16_to_cpu(sas_device_pg0.Slot);
5282 sas_device->device_info = device_info;
5283 sas_device->sas_address = sas_address;
Kashyap, Desai7fbae672010-06-17 13:45:17 +05305284 sas_device->phy = sas_device_pg0.PhyNum;
Eric Moore635374e2009-03-09 01:21:12 -06005285
5286 /* get enclosure_logical_id */
Kashyap, Desai15052c92009-08-07 19:33:17 +05305287 if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
5288 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5289 sas_device->enclosure_handle)))
Eric Moore635374e2009-03-09 01:21:12 -06005290 sas_device->enclosure_logical_id =
5291 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
Eric Moore635374e2009-03-09 01:21:12 -06005292
5293 /* get device name */
5294 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5295
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305296 if (ioc->wait_for_discovery_to_complete)
Eric Moore635374e2009-03-09 01:21:12 -06005297 _scsih_sas_device_init_add(ioc, sas_device);
5298 else
5299 _scsih_sas_device_add(ioc, sas_device);
5300
5301 return 0;
5302}
5303
5304/**
Kashyap, Desai1278b112010-03-09 17:34:13 +05305305 * _scsih_remove_device - removing sas device object
5306 * @ioc: per adapter object
5307 * @sas_device_delete: the sas_device object
5308 *
5309 * Return nothing.
5310 */
5311static void
5312_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
5313 struct _sas_device *sas_device)
5314{
Kashyap, Desai1278b112010-03-09 17:34:13 +05305315 struct MPT2SAS_TARGET *sas_target_priv_data;
Kashyap, Desai34a03be2009-08-20 13:23:19 +05305316
Kashyap, Desai1278b112010-03-09 17:34:13 +05305317 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: "
5318 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305319 sas_device->handle, (unsigned long long)
5320 sas_device->sas_address));
Kashyap, Desai1278b112010-03-09 17:34:13 +05305321
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305322 if (sas_device->starget && sas_device->starget->hostdata) {
5323 sas_target_priv_data = sas_device->starget->hostdata;
Kashyap, Desai1278b112010-03-09 17:34:13 +05305324 sas_target_priv_data->deleted = 1;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305325 _scsih_ublock_io_device(ioc, sas_device->handle);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305326 sas_target_priv_data->handle =
5327 MPT2SAS_INVALID_DEVICE_HANDLE;
Kashyap, Desai1278b112010-03-09 17:34:13 +05305328 }
5329
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05305330 if (!ioc->hide_drives)
5331 mpt2sas_transport_port_remove(ioc,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305332 sas_device->sas_address,
5333 sas_device->sas_address_parent);
Kashyap, Desai1278b112010-03-09 17:34:13 +05305334
5335 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305336 "(0x%016llx)\n", ioc->name, sas_device->handle,
5337 (unsigned long long) sas_device->sas_address);
Kashyap, Desai1278b112010-03-09 17:34:13 +05305338
5339 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: "
5340 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305341 sas_device->handle, (unsigned long long)
5342 sas_device->sas_address));
5343 kfree(sas_device);
5344}
5345/**
5346 * _scsih_device_remove_by_handle - removing device object by handle
5347 * @ioc: per adapter object
5348 * @handle: device handle
5349 *
5350 * Return nothing.
5351 */
5352static void
5353_scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
5354{
5355 struct _sas_device *sas_device;
5356 unsigned long flags;
5357
5358 if (ioc->shost_recovery)
5359 return;
5360
5361 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5362 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
5363 if (sas_device)
5364 list_del(&sas_device->list);
5365 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5366 if (sas_device)
5367 _scsih_remove_device(ioc, sas_device);
Eric Moore635374e2009-03-09 01:21:12 -06005368}
5369
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305370/**
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305371 * mpt2sas_device_remove_by_sas_address - removing device object by sas address
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305372 * @ioc: per adapter object
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305373 * @sas_address: device sas_address
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305374 *
5375 * Return nothing.
5376 */
5377void
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305378mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
5379 u64 sas_address)
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305380{
5381 struct _sas_device *sas_device;
5382 unsigned long flags;
5383
5384 if (ioc->shost_recovery)
5385 return;
5386
5387 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5388 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5389 sas_address);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305390 if (sas_device)
5391 list_del(&sas_device->list);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305392 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305393 if (sas_device)
5394 _scsih_remove_device(ioc, sas_device);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305395}
Eric Moore635374e2009-03-09 01:21:12 -06005396#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5397/**
5398 * _scsih_sas_topology_change_event_debug - debug for topology event
5399 * @ioc: per adapter object
5400 * @event_data: event data payload
5401 * Context: user.
5402 */
5403static void
5404_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5405 Mpi2EventDataSasTopologyChangeList_t *event_data)
5406{
5407 int i;
5408 u16 handle;
5409 u16 reason_code;
5410 u8 phy_number;
5411 char *status_str = NULL;
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305412 u8 link_rate, prev_link_rate;
Eric Moore635374e2009-03-09 01:21:12 -06005413
5414 switch (event_data->ExpStatus) {
5415 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
5416 status_str = "add";
5417 break;
5418 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
5419 status_str = "remove";
5420 break;
5421 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305422 case 0:
Eric Moore635374e2009-03-09 01:21:12 -06005423 status_str = "responding";
5424 break;
5425 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
5426 status_str = "remove delay";
5427 break;
5428 default:
5429 status_str = "unknown status";
5430 break;
5431 }
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305432 printk(MPT2SAS_INFO_FMT "sas topology change: (%s)\n",
Eric Moore635374e2009-03-09 01:21:12 -06005433 ioc->name, status_str);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305434 printk(KERN_INFO "\thandle(0x%04x), enclosure_handle(0x%04x) "
Eric Moore635374e2009-03-09 01:21:12 -06005435 "start_phy(%02d), count(%d)\n",
5436 le16_to_cpu(event_data->ExpanderDevHandle),
5437 le16_to_cpu(event_data->EnclosureHandle),
5438 event_data->StartPhyNum, event_data->NumEntries);
5439 for (i = 0; i < event_data->NumEntries; i++) {
5440 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5441 if (!handle)
5442 continue;
5443 phy_number = event_data->StartPhyNum + i;
5444 reason_code = event_data->PHY[i].PhyStatus &
5445 MPI2_EVENT_SAS_TOPO_RC_MASK;
5446 switch (reason_code) {
5447 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305448 status_str = "target add";
Eric Moore635374e2009-03-09 01:21:12 -06005449 break;
5450 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305451 status_str = "target remove";
Eric Moore635374e2009-03-09 01:21:12 -06005452 break;
5453 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305454 status_str = "delay target remove";
Eric Moore635374e2009-03-09 01:21:12 -06005455 break;
5456 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305457 status_str = "link rate change";
Eric Moore635374e2009-03-09 01:21:12 -06005458 break;
5459 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305460 status_str = "target responding";
Eric Moore635374e2009-03-09 01:21:12 -06005461 break;
5462 default:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305463 status_str = "unknown";
Eric Moore635374e2009-03-09 01:21:12 -06005464 break;
5465 }
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305466 link_rate = event_data->PHY[i].LinkRate >> 4;
5467 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305468 printk(KERN_INFO "\tphy(%02d), attached_handle(0x%04x): %s:"
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305469 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5470 handle, status_str, link_rate, prev_link_rate);
5471
Eric Moore635374e2009-03-09 01:21:12 -06005472 }
5473}
5474#endif
5475
5476/**
5477 * _scsih_sas_topology_change_event - handle topology changes
5478 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305479 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005480 * Context: user.
5481 *
5482 */
5483static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305484_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
Eric Moore635374e2009-03-09 01:21:12 -06005485 struct fw_event_work *fw_event)
5486{
5487 int i;
5488 u16 parent_handle, handle;
5489 u16 reason_code;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305490 u8 phy_number, max_phys;
Eric Moore635374e2009-03-09 01:21:12 -06005491 struct _sas_node *sas_expander;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305492 u64 sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06005493 unsigned long flags;
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305494 u8 link_rate, prev_link_rate;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305495 Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
Eric Moore635374e2009-03-09 01:21:12 -06005496
5497#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5498 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5499 _scsih_sas_topology_change_event_debug(ioc, event_data);
5500#endif
5501
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305502 if (ioc->remove_host || ioc->pci_error_recovery)
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305503 return;
5504
Eric Moore635374e2009-03-09 01:21:12 -06005505 if (!ioc->sas_hba.num_phys)
5506 _scsih_sas_host_add(ioc);
5507 else
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305508 _scsih_sas_host_refresh(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06005509
5510 if (fw_event->ignore) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305511 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring expander "
Eric Moore635374e2009-03-09 01:21:12 -06005512 "event\n", ioc->name));
5513 return;
5514 }
5515
5516 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5517
5518 /* handle expander add */
5519 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5520 if (_scsih_expander_add(ioc, parent_handle) != 0)
5521 return;
5522
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305523 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5524 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
5525 parent_handle);
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305526 if (sas_expander) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305527 sas_address = sas_expander->sas_address;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305528 max_phys = sas_expander->num_phys;
5529 } else if (parent_handle < ioc->sas_hba.num_phys) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305530 sas_address = ioc->sas_hba.sas_address;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305531 max_phys = ioc->sas_hba.num_phys;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305532 } else {
5533 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305534 return;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305535 }
5536 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305537
Eric Moore635374e2009-03-09 01:21:12 -06005538 /* handle siblings events */
5539 for (i = 0; i < event_data->NumEntries; i++) {
5540 if (fw_event->ignore) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305541 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring "
Eric Moore635374e2009-03-09 01:21:12 -06005542 "expander event\n", ioc->name));
5543 return;
5544 }
Eric Moore3cb54692010-07-08 14:44:34 -06005545 if (ioc->shost_recovery || ioc->remove_host ||
5546 ioc->pci_error_recovery)
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05305547 return;
Kashyap, Desai308609c2009-09-14 11:07:23 +05305548 phy_number = event_data->StartPhyNum + i;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305549 if (phy_number >= max_phys)
5550 continue;
Kashyap, Desai308609c2009-09-14 11:07:23 +05305551 reason_code = event_data->PHY[i].PhyStatus &
5552 MPI2_EVENT_SAS_TOPO_RC_MASK;
5553 if ((event_data->PHY[i].PhyStatus &
5554 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5555 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
Eric Moore635374e2009-03-09 01:21:12 -06005556 continue;
5557 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5558 if (!handle)
5559 continue;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305560 link_rate = event_data->PHY[i].LinkRate >> 4;
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305561 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
Eric Moore635374e2009-03-09 01:21:12 -06005562 switch (reason_code) {
5563 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305564
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305565 if (ioc->shost_recovery)
5566 break;
5567
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305568 if (link_rate == prev_link_rate)
5569 break;
5570
5571 mpt2sas_transport_update_links(ioc, sas_address,
5572 handle, phy_number, link_rate);
5573
Kashyap, Desaib4344272010-03-17 16:24:14 +05305574 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5575 break;
5576
5577 _scsih_check_device(ioc, handle);
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305578 break;
Eric Moore635374e2009-03-09 01:21:12 -06005579 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305580
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305581 if (ioc->shost_recovery)
5582 break;
5583
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305584 mpt2sas_transport_update_links(ioc, sas_address,
5585 handle, phy_number, link_rate);
5586
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305587 _scsih_add_device(ioc, handle, phy_number, 0);
Eric Moore635374e2009-03-09 01:21:12 -06005588 break;
5589 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305590
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305591 _scsih_device_remove_by_handle(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06005592 break;
5593 }
5594 }
5595
5596 /* handle expander removal */
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305597 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5598 sas_expander)
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305599 mpt2sas_expander_remove(ioc, sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06005600
5601}
5602
5603#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5604/**
5605 * _scsih_sas_device_status_change_event_debug - debug for device event
5606 * @event_data: event data payload
5607 * Context: user.
5608 *
5609 * Return nothing.
5610 */
5611static void
5612_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5613 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5614{
5615 char *reason_str = NULL;
5616
5617 switch (event_data->ReasonCode) {
5618 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5619 reason_str = "smart data";
5620 break;
5621 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5622 reason_str = "unsupported device discovered";
5623 break;
5624 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5625 reason_str = "internal device reset";
5626 break;
5627 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5628 reason_str = "internal task abort";
5629 break;
5630 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5631 reason_str = "internal task abort set";
5632 break;
5633 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5634 reason_str = "internal clear task set";
5635 break;
5636 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5637 reason_str = "internal query task";
5638 break;
5639 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5640 reason_str = "sata init failure";
5641 break;
5642 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5643 reason_str = "internal device reset complete";
5644 break;
5645 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5646 reason_str = "internal task abort complete";
5647 break;
5648 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5649 reason_str = "internal async notification";
5650 break;
Kashyap, Desaiec6c2b42009-09-23 17:31:01 +05305651 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5652 reason_str = "expander reduced functionality";
5653 break;
5654 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5655 reason_str = "expander reduced functionality complete";
5656 break;
Eric Moore635374e2009-03-09 01:21:12 -06005657 default:
5658 reason_str = "unknown reason";
5659 break;
5660 }
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305661 printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305662 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5663 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5664 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5665 le16_to_cpu(event_data->TaskTag));
Eric Moore635374e2009-03-09 01:21:12 -06005666 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305667 printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06005668 event_data->ASC, event_data->ASCQ);
5669 printk(KERN_INFO "\n");
5670}
5671#endif
5672
5673/**
5674 * _scsih_sas_device_status_change_event - handle device status change
5675 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305676 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005677 * Context: user.
5678 *
5679 * Return nothing.
5680 */
5681static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305682_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
5683 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005684{
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305685 struct MPT2SAS_TARGET *target_priv_data;
5686 struct _sas_device *sas_device;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05305687 u64 sas_address;
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305688 unsigned long flags;
5689 Mpi2EventDataSasDeviceStatusChange_t *event_data =
5690 fw_event->event_data;
5691
Eric Moore635374e2009-03-09 01:21:12 -06005692#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5693 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305694 _scsih_sas_device_status_change_event_debug(ioc,
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305695 event_data);
Eric Moore635374e2009-03-09 01:21:12 -06005696#endif
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305697
Kashyap, Desaiefe82a12011-01-04 11:34:17 +05305698 /* In MPI Revision K (0xC), the internal device reset complete was
5699 * implemented, so avoid setting tm_busy flag for older firmware.
5700 */
5701 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
5702 return;
5703
Kashyap, Desaif891dcf2010-03-17 16:22:21 +05305704 if (event_data->ReasonCode !=
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305705 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
Kashyap, Desaif891dcf2010-03-17 16:22:21 +05305706 event_data->ReasonCode !=
5707 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305708 return;
5709
5710 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5711 sas_address = le64_to_cpu(event_data->SASAddress);
5712 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5713 sas_address);
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305714
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305715 if (!sas_device || !sas_device->starget) {
5716 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305717 return;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305718 }
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305719
5720 target_priv_data = sas_device->starget->hostdata;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305721 if (!target_priv_data) {
5722 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305723 return;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305724 }
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305725
5726 if (event_data->ReasonCode ==
5727 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
5728 target_priv_data->tm_busy = 1;
5729 else
5730 target_priv_data->tm_busy = 0;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05305731 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06005732}
5733
5734#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5735/**
5736 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event
5737 * @ioc: per adapter object
5738 * @event_data: event data payload
5739 * Context: user.
5740 *
5741 * Return nothing.
5742 */
5743static void
5744_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5745 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
5746{
5747 char *reason_str = NULL;
5748
5749 switch (event_data->ReasonCode) {
5750 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
5751 reason_str = "enclosure add";
5752 break;
5753 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
5754 reason_str = "enclosure remove";
5755 break;
5756 default:
5757 reason_str = "unknown reason";
5758 break;
5759 }
5760
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305761 printk(MPT2SAS_INFO_FMT "enclosure status change: (%s)\n"
Eric Moore635374e2009-03-09 01:21:12 -06005762 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
5763 " number slots(%d)\n", ioc->name, reason_str,
5764 le16_to_cpu(event_data->EnclosureHandle),
5765 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
5766 le16_to_cpu(event_data->StartSlot));
5767}
5768#endif
5769
5770/**
5771 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
5772 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305773 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005774 * Context: user.
5775 *
5776 * Return nothing.
5777 */
5778static void
5779_scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305780 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005781{
5782#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5783 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5784 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305785 fw_event->event_data);
Eric Moore635374e2009-03-09 01:21:12 -06005786#endif
5787}
5788
5789/**
Andrew Mortona78e21d2012-02-08 12:52:22 -08005790 * _scsih_sas_broadcast_primitive_event - handle broadcast events
Eric Moore635374e2009-03-09 01:21:12 -06005791 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305792 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005793 * Context: user.
5794 *
5795 * Return nothing.
5796 */
5797static void
Andrew Mortona78e21d2012-02-08 12:52:22 -08005798_scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305799 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005800{
5801 struct scsi_cmnd *scmd;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305802 struct scsi_device *sdev;
Eric Moore635374e2009-03-09 01:21:12 -06005803 u16 smid, handle;
5804 u32 lun;
5805 struct MPT2SAS_DEVICE *sas_device_priv_data;
5806 u32 termination_count;
5807 u32 query_count;
5808 Mpi2SCSITaskManagementReply_t *mpi_reply;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305809 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
Kashyap, Desai463217b2009-10-05 15:53:06 +05305810 u16 ioc_status;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305811 unsigned long flags;
5812 int r;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305813 u8 max_retries = 0;
5814 u8 task_abort_retries;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305815
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305816 mutex_lock(&ioc->tm_cmds.mutex);
5817 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
5818 "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
5819 event_data->PortWidth));
5820
5821 _scsih_block_io_all_device(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06005822
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305823 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305824 mpi_reply = ioc->tm_cmds.reply;
5825broadcast_aen_retry:
5826
5827 /* sanity checks for retrying this loop */
5828 if (max_retries++ == 5) {
5829 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
5830 ioc->name, __func__));
5831 goto out;
5832 } else if (max_retries > 1)
5833 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
5834 ioc->name, __func__, max_retries - 1));
5835
Eric Moore635374e2009-03-09 01:21:12 -06005836 termination_count = 0;
5837 query_count = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05305838 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305839 if (ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305840 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06005841 scmd = _scsih_scsi_lookup_get(ioc, smid);
5842 if (!scmd)
5843 continue;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305844 sdev = scmd->device;
5845 sas_device_priv_data = sdev->hostdata;
Eric Moore635374e2009-03-09 01:21:12 -06005846 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
5847 continue;
5848 /* skip hidden raid components */
5849 if (sas_device_priv_data->sas_target->flags &
5850 MPT_TARGET_FLAGS_RAID_COMPONENT)
5851 continue;
5852 /* skip volumes */
5853 if (sas_device_priv_data->sas_target->flags &
5854 MPT_TARGET_FLAGS_VOLUME)
5855 continue;
5856
5857 handle = sas_device_priv_data->sas_target->handle;
5858 lun = sas_device_priv_data->lun;
5859 query_count++;
5860
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305861 if (ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305862 goto out;
5863
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305864 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305865 r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
5866 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
5867 TM_MUTEX_OFF);
5868 if (r == FAILED) {
5869 sdev_printk(KERN_WARNING, sdev,
5870 "mpt2sas_scsih_issue_tm: FAILED when sending "
5871 "QUERY_TASK: scmd(%p)\n", scmd);
5872 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5873 goto broadcast_aen_retry;
5874 }
Kashyap, Desai463217b2009-10-05 15:53:06 +05305875 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
5876 & MPI2_IOCSTATUS_MASK;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305877 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5878 sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
5879 "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
5880 scmd);
5881 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5882 goto broadcast_aen_retry;
5883 }
5884
5885 /* see if IO is still owned by IOC and target */
5886 if (mpi_reply->ResponseCode ==
Eric Moore635374e2009-03-09 01:21:12 -06005887 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5888 mpi_reply->ResponseCode ==
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305889 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305890 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06005891 continue;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305892 }
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305893 task_abort_retries = 0;
5894 tm_retry:
5895 if (task_abort_retries++ == 60) {
5896 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
5897 "%s: ABORT_TASK: giving up\n", ioc->name,
5898 __func__));
5899 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5900 goto broadcast_aen_retry;
5901 }
5902
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305903 if (ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305904 goto out_no_lock;
5905
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305906 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5907 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305908 scmd->serial_number, TM_MUTEX_OFF);
5909 if (r == FAILED) {
5910 sdev_printk(KERN_WARNING, sdev,
5911 "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305912 "scmd(%p)\n", scmd);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305913 goto tm_retry;
5914 }
5915
5916 if (task_abort_retries > 1)
5917 sdev_printk(KERN_WARNING, sdev,
5918 "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
5919 " scmd(%p)\n",
5920 task_abort_retries - 1, scmd);
5921
Eric Moore635374e2009-03-09 01:21:12 -06005922 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305923 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06005924 }
Eric Moore635374e2009-03-09 01:21:12 -06005925
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305926 if (ioc->broadcast_aen_pending) {
5927 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
5928 " pending AEN\n", ioc->name, __func__));
5929 ioc->broadcast_aen_pending = 0;
5930 goto broadcast_aen_retry;
5931 }
5932
5933 out:
5934 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5935 out_no_lock:
5936
5937 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06005938 "%s - exit, query_count = %d termination_count = %d\n",
5939 ioc->name, __func__, query_count, termination_count));
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305940
5941 ioc->broadcast_aen_busy = 0;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305942 if (!ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305943 _scsih_ublock_io_all_device(ioc);
5944 mutex_unlock(&ioc->tm_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06005945}
5946
5947/**
5948 * _scsih_sas_discovery_event - handle discovery events
5949 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305950 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005951 * Context: user.
5952 *
5953 * Return nothing.
5954 */
5955static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305956_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
5957 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005958{
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305959 Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
5960
Eric Moore635374e2009-03-09 01:21:12 -06005961#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5962 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305963 printk(MPT2SAS_INFO_FMT "discovery event: (%s)", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06005964 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
5965 "start" : "stop");
5966 if (event_data->DiscoveryStatus)
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05305967 printk("discovery_status(0x%08x)",
5968 le32_to_cpu(event_data->DiscoveryStatus));
Eric Moore635374e2009-03-09 01:21:12 -06005969 printk("\n");
5970 }
5971#endif
5972
5973 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
5974 !ioc->sas_hba.num_phys)
5975 _scsih_sas_host_add(ioc);
5976}
5977
5978/**
5979 * _scsih_reprobe_lun - reprobing lun
5980 * @sdev: scsi device struct
5981 * @no_uld_attach: sdev->no_uld_attach flag setting
5982 *
5983 **/
5984static void
5985_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
5986{
5987 int rc;
5988
5989 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
5990 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
5991 sdev->no_uld_attach ? "hidding" : "exposing");
5992 rc = scsi_device_reprobe(sdev);
5993}
5994
5995/**
Eric Moore635374e2009-03-09 01:21:12 -06005996 * _scsih_sas_volume_add - add new volume
5997 * @ioc: per adapter object
5998 * @element: IR config element data
5999 * Context: user.
6000 *
6001 * Return nothing.
6002 */
6003static void
6004_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
6005 Mpi2EventIrConfigElement_t *element)
6006{
6007 struct _raid_device *raid_device;
6008 unsigned long flags;
6009 u64 wwid;
6010 u16 handle = le16_to_cpu(element->VolDevHandle);
6011 int rc;
6012
Eric Moore635374e2009-03-09 01:21:12 -06006013 mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
6014 if (!wwid) {
6015 printk(MPT2SAS_ERR_FMT
6016 "failure at %s:%d/%s()!\n", ioc->name,
6017 __FILE__, __LINE__, __func__);
6018 return;
6019 }
6020
6021 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6022 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
6023 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6024
6025 if (raid_device)
6026 return;
6027
6028 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6029 if (!raid_device) {
6030 printk(MPT2SAS_ERR_FMT
6031 "failure at %s:%d/%s()!\n", ioc->name,
6032 __FILE__, __LINE__, __func__);
6033 return;
6034 }
6035
6036 raid_device->id = ioc->sas_id++;
6037 raid_device->channel = RAID_CHANNEL;
6038 raid_device->handle = handle;
6039 raid_device->wwid = wwid;
6040 _scsih_raid_device_add(ioc, raid_device);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306041 if (!ioc->wait_for_discovery_to_complete) {
Eric Moore635374e2009-03-09 01:21:12 -06006042 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6043 raid_device->id, 0);
6044 if (rc)
6045 _scsih_raid_device_remove(ioc, raid_device);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306046 } else {
6047 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06006048 _scsih_determine_boot_device(ioc, raid_device, 1);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306049 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6050 }
Eric Moore635374e2009-03-09 01:21:12 -06006051}
6052
6053/**
6054 * _scsih_sas_volume_delete - delete volume
6055 * @ioc: per adapter object
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306056 * @handle: volume device handle
Eric Moore635374e2009-03-09 01:21:12 -06006057 * Context: user.
6058 *
6059 * Return nothing.
6060 */
6061static void
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306062_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle)
Eric Moore635374e2009-03-09 01:21:12 -06006063{
6064 struct _raid_device *raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06006065 unsigned long flags;
6066 struct MPT2SAS_TARGET *sas_target_priv_data;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306067 struct scsi_target *starget = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06006068
Eric Moore635374e2009-03-09 01:21:12 -06006069 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6070 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306071 if (raid_device) {
6072 if (raid_device->starget) {
6073 starget = raid_device->starget;
6074 sas_target_priv_data = starget->hostdata;
6075 sas_target_priv_data->deleted = 1;
6076 }
6077 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
6078 "(0x%016llx)\n", ioc->name, raid_device->handle,
6079 (unsigned long long) raid_device->wwid);
6080 list_del(&raid_device->list);
6081 kfree(raid_device);
Eric Moore635374e2009-03-09 01:21:12 -06006082 }
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306083 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6084 if (starget)
6085 scsi_remove_target(&starget->dev);
Eric Moore635374e2009-03-09 01:21:12 -06006086}
6087
6088/**
6089 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
6090 * @ioc: per adapter object
6091 * @element: IR config element data
6092 * Context: user.
6093 *
6094 * Return nothing.
6095 */
6096static void
6097_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
6098 Mpi2EventIrConfigElement_t *element)
6099{
6100 struct _sas_device *sas_device;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306101 struct scsi_target *starget = NULL;
6102 struct MPT2SAS_TARGET *sas_target_priv_data;
Eric Moore635374e2009-03-09 01:21:12 -06006103 unsigned long flags;
6104 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6105
6106 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6107 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306108 if (sas_device) {
6109 sas_device->volume_handle = 0;
6110 sas_device->volume_wwid = 0;
6111 clear_bit(handle, ioc->pd_handles);
6112 if (sas_device->starget && sas_device->starget->hostdata) {
6113 starget = sas_device->starget;
6114 sas_target_priv_data = starget->hostdata;
6115 sas_target_priv_data->flags &=
6116 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
6117 }
6118 }
Eric Moore635374e2009-03-09 01:21:12 -06006119 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6120 if (!sas_device)
6121 return;
6122
6123 /* exposing raid component */
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306124 if (starget)
6125 starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
Eric Moore635374e2009-03-09 01:21:12 -06006126}
6127
6128/**
6129 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
6130 * @ioc: per adapter object
6131 * @element: IR config element data
6132 * Context: user.
6133 *
6134 * Return nothing.
6135 */
6136static void
6137_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
6138 Mpi2EventIrConfigElement_t *element)
6139{
6140 struct _sas_device *sas_device;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306141 struct scsi_target *starget = NULL;
6142 struct MPT2SAS_TARGET *sas_target_priv_data;
Eric Moore635374e2009-03-09 01:21:12 -06006143 unsigned long flags;
6144 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306145 u16 volume_handle = 0;
6146 u64 volume_wwid = 0;
6147
6148 mpt2sas_config_get_volume_handle(ioc, handle, &volume_handle);
6149 if (volume_handle)
6150 mpt2sas_config_get_volume_wwid(ioc, volume_handle,
6151 &volume_wwid);
Eric Moore635374e2009-03-09 01:21:12 -06006152
6153 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6154 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306155 if (sas_device) {
6156 set_bit(handle, ioc->pd_handles);
6157 if (sas_device->starget && sas_device->starget->hostdata) {
6158 starget = sas_device->starget;
6159 sas_target_priv_data = starget->hostdata;
6160 sas_target_priv_data->flags |=
6161 MPT_TARGET_FLAGS_RAID_COMPONENT;
6162 sas_device->volume_handle = volume_handle;
6163 sas_device->volume_wwid = volume_wwid;
6164 }
6165 }
Eric Moore635374e2009-03-09 01:21:12 -06006166 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6167 if (!sas_device)
6168 return;
6169
6170 /* hiding raid component */
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306171 if (starget)
6172 starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
Eric Moore635374e2009-03-09 01:21:12 -06006173}
6174
6175/**
6176 * _scsih_sas_pd_delete - delete pd component
6177 * @ioc: per adapter object
6178 * @element: IR config element data
6179 * Context: user.
6180 *
6181 * Return nothing.
6182 */
6183static void
6184_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
6185 Mpi2EventIrConfigElement_t *element)
6186{
Eric Moore635374e2009-03-09 01:21:12 -06006187 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6188
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306189 _scsih_device_remove_by_handle(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06006190}
6191
6192/**
6193 * _scsih_sas_pd_add - remove pd component
6194 * @ioc: per adapter object
6195 * @element: IR config element data
6196 * Context: user.
6197 *
6198 * Return nothing.
6199 */
6200static void
6201_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
6202 Mpi2EventIrConfigElement_t *element)
6203{
6204 struct _sas_device *sas_device;
6205 unsigned long flags;
6206 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
Kashyap, Desai62727a72009-08-07 19:35:18 +05306207 Mpi2ConfigReply_t mpi_reply;
6208 Mpi2SasDevicePage0_t sas_device_pg0;
6209 u32 ioc_status;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306210 u64 sas_address;
6211 u16 parent_handle;
Eric Moore635374e2009-03-09 01:21:12 -06006212
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306213 set_bit(handle, ioc->pd_handles);
6214
Eric Moore635374e2009-03-09 01:21:12 -06006215 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6216 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6217 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306218 if (sas_device)
Kashyap, Desai62727a72009-08-07 19:35:18 +05306219 return;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306220
6221 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
6222 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
6223 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6224 ioc->name, __FILE__, __LINE__, __func__);
6225 return;
6226 }
6227
6228 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6229 MPI2_IOCSTATUS_MASK;
6230 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6231 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6232 ioc->name, __FILE__, __LINE__, __func__);
6233 return;
6234 }
6235
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306236 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6237 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6238 mpt2sas_transport_update_links(ioc, sas_address, handle,
6239 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
Kashyap, Desai62727a72009-08-07 19:35:18 +05306240
6241 _scsih_add_device(ioc, handle, 0, 1);
Eric Moore635374e2009-03-09 01:21:12 -06006242}
6243
6244#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
6245/**
6246 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
6247 * @ioc: per adapter object
6248 * @event_data: event data payload
6249 * Context: user.
6250 *
6251 * Return nothing.
6252 */
6253static void
6254_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
6255 Mpi2EventDataIrConfigChangeList_t *event_data)
6256{
6257 Mpi2EventIrConfigElement_t *element;
6258 u8 element_type;
6259 int i;
6260 char *reason_str = NULL, *element_str = NULL;
6261
6262 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6263
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05306264 printk(MPT2SAS_INFO_FMT "raid config change: (%s), elements(%d)\n",
Eric Moore635374e2009-03-09 01:21:12 -06006265 ioc->name, (le32_to_cpu(event_data->Flags) &
6266 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
6267 "foreign" : "native", event_data->NumElements);
6268 for (i = 0; i < event_data->NumElements; i++, element++) {
6269 switch (element->ReasonCode) {
6270 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6271 reason_str = "add";
6272 break;
6273 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6274 reason_str = "remove";
6275 break;
6276 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
6277 reason_str = "no change";
6278 break;
6279 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6280 reason_str = "hide";
6281 break;
6282 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6283 reason_str = "unhide";
6284 break;
6285 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6286 reason_str = "volume_created";
6287 break;
6288 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6289 reason_str = "volume_deleted";
6290 break;
6291 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6292 reason_str = "pd_created";
6293 break;
6294 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6295 reason_str = "pd_deleted";
6296 break;
6297 default:
6298 reason_str = "unknown reason";
6299 break;
6300 }
6301 element_type = le16_to_cpu(element->ElementFlags) &
6302 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
6303 switch (element_type) {
6304 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
6305 element_str = "volume";
6306 break;
6307 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
6308 element_str = "phys disk";
6309 break;
6310 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
6311 element_str = "hot spare";
6312 break;
6313 default:
6314 element_str = "unknown element";
6315 break;
6316 }
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05306317 printk(KERN_INFO "\t(%s:%s), vol handle(0x%04x), "
Eric Moore635374e2009-03-09 01:21:12 -06006318 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
6319 reason_str, le16_to_cpu(element->VolDevHandle),
6320 le16_to_cpu(element->PhysDiskDevHandle),
6321 element->PhysDiskNum);
6322 }
6323}
6324#endif
6325
6326/**
6327 * _scsih_sas_ir_config_change_event - handle ir configuration change events
6328 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306329 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006330 * Context: user.
6331 *
6332 * Return nothing.
6333 */
6334static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306335_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
6336 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006337{
6338 Mpi2EventIrConfigElement_t *element;
6339 int i;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306340 u8 foreign_config;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306341 Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
Eric Moore635374e2009-03-09 01:21:12 -06006342
6343#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306344 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6345 && !ioc->hide_ir_msg)
Eric Moore635374e2009-03-09 01:21:12 -06006346 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6347
6348#endif
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306349
6350 if (ioc->shost_recovery)
6351 return;
6352
Kashyap, Desai62727a72009-08-07 19:35:18 +05306353 foreign_config = (le32_to_cpu(event_data->Flags) &
6354 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
Eric Moore635374e2009-03-09 01:21:12 -06006355
6356 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6357 for (i = 0; i < event_data->NumElements; i++, element++) {
6358
6359 switch (element->ReasonCode) {
6360 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6361 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
Kashyap, Desai62727a72009-08-07 19:35:18 +05306362 if (!foreign_config)
6363 _scsih_sas_volume_add(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006364 break;
6365 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6366 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
Kashyap, Desai62727a72009-08-07 19:35:18 +05306367 if (!foreign_config)
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306368 _scsih_sas_volume_delete(ioc,
6369 le16_to_cpu(element->VolDevHandle));
Eric Moore635374e2009-03-09 01:21:12 -06006370 break;
6371 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306372 if (!ioc->is_warpdrive)
6373 _scsih_sas_pd_hide(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006374 break;
6375 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306376 if (!ioc->is_warpdrive)
6377 _scsih_sas_pd_expose(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006378 break;
6379 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306380 if (!ioc->is_warpdrive)
6381 _scsih_sas_pd_add(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006382 break;
6383 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306384 if (!ioc->is_warpdrive)
6385 _scsih_sas_pd_delete(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006386 break;
6387 }
6388 }
6389}
6390
6391/**
6392 * _scsih_sas_ir_volume_event - IR volume event
6393 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306394 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006395 * Context: user.
6396 *
6397 * Return nothing.
6398 */
6399static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306400_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
6401 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006402{
6403 u64 wwid;
6404 unsigned long flags;
6405 struct _raid_device *raid_device;
6406 u16 handle;
6407 u32 state;
6408 int rc;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306409 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
Eric Moore635374e2009-03-09 01:21:12 -06006410
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306411 if (ioc->shost_recovery)
6412 return;
6413
Eric Moore635374e2009-03-09 01:21:12 -06006414 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6415 return;
6416
6417 handle = le16_to_cpu(event_data->VolDevHandle);
6418 state = le32_to_cpu(event_data->NewValue);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306419 if (!ioc->hide_ir_msg)
6420 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
6421 "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
6422 le32_to_cpu(event_data->PreviousValue), state));
Eric Moore635374e2009-03-09 01:21:12 -06006423
Eric Moore635374e2009-03-09 01:21:12 -06006424 switch (state) {
6425 case MPI2_RAID_VOL_STATE_MISSING:
6426 case MPI2_RAID_VOL_STATE_FAILED:
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306427 _scsih_sas_volume_delete(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06006428 break;
6429
6430 case MPI2_RAID_VOL_STATE_ONLINE:
6431 case MPI2_RAID_VOL_STATE_DEGRADED:
6432 case MPI2_RAID_VOL_STATE_OPTIMAL:
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306433
6434 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6435 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6436 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6437
Eric Moore635374e2009-03-09 01:21:12 -06006438 if (raid_device)
6439 break;
6440
6441 mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
6442 if (!wwid) {
6443 printk(MPT2SAS_ERR_FMT
6444 "failure at %s:%d/%s()!\n", ioc->name,
6445 __FILE__, __LINE__, __func__);
6446 break;
6447 }
6448
6449 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6450 if (!raid_device) {
6451 printk(MPT2SAS_ERR_FMT
6452 "failure at %s:%d/%s()!\n", ioc->name,
6453 __FILE__, __LINE__, __func__);
6454 break;
6455 }
6456
6457 raid_device->id = ioc->sas_id++;
6458 raid_device->channel = RAID_CHANNEL;
6459 raid_device->handle = handle;
6460 raid_device->wwid = wwid;
6461 _scsih_raid_device_add(ioc, raid_device);
6462 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6463 raid_device->id, 0);
6464 if (rc)
6465 _scsih_raid_device_remove(ioc, raid_device);
6466 break;
6467
6468 case MPI2_RAID_VOL_STATE_INITIALIZING:
6469 default:
6470 break;
6471 }
6472}
6473
6474/**
6475 * _scsih_sas_ir_physical_disk_event - PD event
6476 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306477 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006478 * Context: user.
6479 *
6480 * Return nothing.
6481 */
6482static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306483_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
6484 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006485{
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306486 u16 handle, parent_handle;
Eric Moore635374e2009-03-09 01:21:12 -06006487 u32 state;
6488 struct _sas_device *sas_device;
6489 unsigned long flags;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306490 Mpi2ConfigReply_t mpi_reply;
6491 Mpi2SasDevicePage0_t sas_device_pg0;
6492 u32 ioc_status;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306493 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306494 u64 sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06006495
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306496 if (ioc->shost_recovery)
6497 return;
6498
Eric Moore635374e2009-03-09 01:21:12 -06006499 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6500 return;
6501
6502 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6503 state = le32_to_cpu(event_data->NewValue);
6504
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306505 if (!ioc->hide_ir_msg)
6506 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
6507 "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
6508 le32_to_cpu(event_data->PreviousValue), state));
Eric Moore635374e2009-03-09 01:21:12 -06006509
Eric Moore635374e2009-03-09 01:21:12 -06006510 switch (state) {
Eric Moore635374e2009-03-09 01:21:12 -06006511 case MPI2_RAID_PD_STATE_ONLINE:
6512 case MPI2_RAID_PD_STATE_DEGRADED:
6513 case MPI2_RAID_PD_STATE_REBUILDING:
6514 case MPI2_RAID_PD_STATE_OPTIMAL:
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306515 case MPI2_RAID_PD_STATE_HOT_SPARE:
6516
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306517 if (!ioc->is_warpdrive)
6518 set_bit(handle, ioc->pd_handles);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306519
6520 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6521 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6522 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6523
6524 if (sas_device)
Kashyap, Desai62727a72009-08-07 19:35:18 +05306525 return;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306526
6527 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6528 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6529 handle))) {
6530 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6531 ioc->name, __FILE__, __LINE__, __func__);
6532 return;
6533 }
6534
6535 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6536 MPI2_IOCSTATUS_MASK;
6537 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6538 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6539 ioc->name, __FILE__, __LINE__, __func__);
6540 return;
6541 }
6542
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306543 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6544 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6545 mpt2sas_transport_update_links(ioc, sas_address, handle,
6546 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
Kashyap, Desai62727a72009-08-07 19:35:18 +05306547
6548 _scsih_add_device(ioc, handle, 0, 1);
6549
Eric Moore635374e2009-03-09 01:21:12 -06006550 break;
6551
Kashyap, Desai62727a72009-08-07 19:35:18 +05306552 case MPI2_RAID_PD_STATE_OFFLINE:
Eric Moore635374e2009-03-09 01:21:12 -06006553 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6554 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
Eric Moore635374e2009-03-09 01:21:12 -06006555 default:
6556 break;
6557 }
6558}
6559
6560#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
6561/**
6562 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6563 * @ioc: per adapter object
6564 * @event_data: event data payload
6565 * Context: user.
6566 *
6567 * Return nothing.
6568 */
6569static void
6570_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
6571 Mpi2EventDataIrOperationStatus_t *event_data)
6572{
6573 char *reason_str = NULL;
6574
6575 switch (event_data->RAIDOperation) {
6576 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6577 reason_str = "resync";
6578 break;
6579 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6580 reason_str = "online capacity expansion";
6581 break;
6582 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6583 reason_str = "consistency check";
6584 break;
Kashyap, Desaiec6c2b42009-09-23 17:31:01 +05306585 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6586 reason_str = "background init";
6587 break;
6588 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
6589 reason_str = "make data consistent";
Eric Moore635374e2009-03-09 01:21:12 -06006590 break;
6591 }
6592
Kashyap, Desaiec6c2b42009-09-23 17:31:01 +05306593 if (!reason_str)
6594 return;
6595
Eric Moore635374e2009-03-09 01:21:12 -06006596 printk(MPT2SAS_INFO_FMT "raid operational status: (%s)"
6597 "\thandle(0x%04x), percent complete(%d)\n",
6598 ioc->name, reason_str,
6599 le16_to_cpu(event_data->VolDevHandle),
6600 event_data->PercentComplete);
6601}
6602#endif
6603
6604/**
6605 * _scsih_sas_ir_operation_status_event - handle RAID operation events
6606 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306607 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006608 * Context: user.
6609 *
6610 * Return nothing.
6611 */
6612static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306613_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
6614 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006615{
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306616 Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
6617 static struct _raid_device *raid_device;
6618 unsigned long flags;
6619 u16 handle;
6620
Eric Moore635374e2009-03-09 01:21:12 -06006621#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306622 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6623 && !ioc->hide_ir_msg)
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306624 _scsih_sas_ir_operation_status_event_debug(ioc,
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306625 event_data);
Eric Moore635374e2009-03-09 01:21:12 -06006626#endif
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306627
6628 /* code added for raid transport support */
6629 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
6630
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306631 spin_lock_irqsave(&ioc->raid_device_lock, flags);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306632 handle = le16_to_cpu(event_data->VolDevHandle);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306633 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306634 if (raid_device)
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306635 raid_device->percent_complete =
6636 event_data->PercentComplete;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306637 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306638 }
Eric Moore635374e2009-03-09 01:21:12 -06006639}
6640
6641/**
Kashyap, Desai14695852010-03-30 10:52:44 +05306642 * _scsih_prep_device_scan - initialize parameters prior to device scan
6643 * @ioc: per adapter object
6644 *
6645 * Set the deleted flag prior to device scan. If the device is found during
6646 * the scan, then we clear the deleted flag.
6647 */
6648static void
6649_scsih_prep_device_scan(struct MPT2SAS_ADAPTER *ioc)
6650{
6651 struct MPT2SAS_DEVICE *sas_device_priv_data;
6652 struct scsi_device *sdev;
6653
6654 shost_for_each_device(sdev, ioc->shost) {
6655 sas_device_priv_data = sdev->hostdata;
6656 if (sas_device_priv_data && sas_device_priv_data->sas_target)
6657 sas_device_priv_data->sas_target->deleted = 1;
6658 }
6659}
6660
6661/**
Eric Moore635374e2009-03-09 01:21:12 -06006662 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
6663 * @ioc: per adapter object
6664 * @sas_address: sas address
6665 * @slot: enclosure slot id
6666 * @handle: device handle
6667 *
6668 * After host reset, find out whether devices are still responding.
6669 * Used in _scsi_remove_unresponsive_sas_devices.
6670 *
6671 * Return nothing.
6672 */
6673static void
6674_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
6675 u16 slot, u16 handle)
6676{
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306677 struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06006678 struct scsi_target *starget;
6679 struct _sas_device *sas_device;
6680 unsigned long flags;
6681
6682 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6683 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
6684 if (sas_device->sas_address == sas_address &&
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306685 sas_device->slot == slot) {
Eric Moore635374e2009-03-09 01:21:12 -06006686 sas_device->responding = 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05306687 starget = sas_device->starget;
Kashyap, Desai14695852010-03-30 10:52:44 +05306688 if (starget && starget->hostdata) {
6689 sas_target_priv_data = starget->hostdata;
6690 sas_target_priv_data->tm_busy = 0;
6691 sas_target_priv_data->deleted = 0;
6692 } else
6693 sas_target_priv_data = NULL;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306694 if (starget)
6695 starget_printk(KERN_INFO, starget,
6696 "handle(0x%04x), sas_addr(0x%016llx), "
6697 "enclosure logical id(0x%016llx), "
6698 "slot(%d)\n", handle,
6699 (unsigned long long)sas_device->sas_address,
6700 (unsigned long long)
6701 sas_device->enclosure_logical_id,
6702 sas_device->slot);
Eric Moore635374e2009-03-09 01:21:12 -06006703 if (sas_device->handle == handle)
6704 goto out;
6705 printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
6706 sas_device->handle);
6707 sas_device->handle = handle;
Kashyap, Desai14695852010-03-30 10:52:44 +05306708 if (sas_target_priv_data)
6709 sas_target_priv_data->handle = handle;
Eric Moore635374e2009-03-09 01:21:12 -06006710 goto out;
6711 }
6712 }
6713 out:
6714 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6715}
6716
6717/**
6718 * _scsih_search_responding_sas_devices -
6719 * @ioc: per adapter object
6720 *
6721 * After host reset, find out whether devices are still responding.
6722 * If not remove.
6723 *
6724 * Return nothing.
6725 */
6726static void
6727_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6728{
6729 Mpi2SasDevicePage0_t sas_device_pg0;
6730 Mpi2ConfigReply_t mpi_reply;
6731 u16 ioc_status;
6732 __le64 sas_address;
6733 u16 handle;
6734 u32 device_info;
6735 u16 slot;
6736
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306737 printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006738
6739 if (list_empty(&ioc->sas_device_list))
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306740 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006741
6742 handle = 0xFFFF;
6743 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6744 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6745 handle))) {
6746 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6747 MPI2_IOCSTATUS_MASK;
6748 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6749 break;
6750 handle = le16_to_cpu(sas_device_pg0.DevHandle);
6751 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
6752 if (!(_scsih_is_end_device(device_info)))
6753 continue;
6754 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
6755 slot = le16_to_cpu(sas_device_pg0.Slot);
6756 _scsih_mark_responding_sas_device(ioc, sas_address, slot,
6757 handle);
6758 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306759out:
6760 printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
6761 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006762}
6763
6764/**
6765 * _scsih_mark_responding_raid_device - mark a raid_device as responding
6766 * @ioc: per adapter object
6767 * @wwid: world wide identifier for raid volume
6768 * @handle: device handle
6769 *
6770 * After host reset, find out whether devices are still responding.
6771 * Used in _scsi_remove_unresponsive_raid_devices.
6772 *
6773 * Return nothing.
6774 */
6775static void
6776_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
6777 u16 handle)
6778{
6779 struct MPT2SAS_TARGET *sas_target_priv_data;
6780 struct scsi_target *starget;
6781 struct _raid_device *raid_device;
6782 unsigned long flags;
6783
6784 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6785 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
6786 if (raid_device->wwid == wwid && raid_device->starget) {
Kashyap, Desai14695852010-03-30 10:52:44 +05306787 starget = raid_device->starget;
6788 if (starget && starget->hostdata) {
6789 sas_target_priv_data = starget->hostdata;
6790 sas_target_priv_data->deleted = 0;
6791 } else
6792 sas_target_priv_data = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06006793 raid_device->responding = 1;
nagalakshmi.nandigama@lsi.com30c43282011-12-01 07:52:56 +05306794 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06006795 starget_printk(KERN_INFO, raid_device->starget,
6796 "handle(0x%04x), wwid(0x%016llx)\n", handle,
6797 (unsigned long long)raid_device->wwid);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306798 /*
6799 * WARPDRIVE: The handles of the PDs might have changed
6800 * across the host reset so re-initialize the
6801 * required data for Direct IO
6802 */
6803 _scsih_init_warpdrive_properties(ioc, raid_device);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306804 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6805 if (raid_device->handle == handle) {
6806 spin_unlock_irqrestore(&ioc->raid_device_lock,
6807 flags);
nagalakshmi.nandigama@lsi.com30c43282011-12-01 07:52:56 +05306808 return;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306809 }
Eric Moore635374e2009-03-09 01:21:12 -06006810 printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
6811 raid_device->handle);
6812 raid_device->handle = handle;
Kashyap, Desai14695852010-03-30 10:52:44 +05306813 if (sas_target_priv_data)
6814 sas_target_priv_data->handle = handle;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306815 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
nagalakshmi.nandigama@lsi.com30c43282011-12-01 07:52:56 +05306816 return;
Eric Moore635374e2009-03-09 01:21:12 -06006817 }
6818 }
nagalakshmi.nandigama@lsi.com30c43282011-12-01 07:52:56 +05306819
Eric Moore635374e2009-03-09 01:21:12 -06006820 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6821}
6822
6823/**
6824 * _scsih_search_responding_raid_devices -
6825 * @ioc: per adapter object
6826 *
6827 * After host reset, find out whether devices are still responding.
6828 * If not remove.
6829 *
6830 * Return nothing.
6831 */
6832static void
6833_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
6834{
6835 Mpi2RaidVolPage1_t volume_pg1;
Kashyap, Desaid417d1c2010-06-17 13:48:10 +05306836 Mpi2RaidVolPage0_t volume_pg0;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306837 Mpi2RaidPhysDiskPage0_t pd_pg0;
Eric Moore635374e2009-03-09 01:21:12 -06006838 Mpi2ConfigReply_t mpi_reply;
6839 u16 ioc_status;
6840 u16 handle;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306841 u8 phys_disk_num;
Eric Moore635374e2009-03-09 01:21:12 -06006842
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306843 if (!ioc->ir_firmware)
6844 return;
6845
6846 printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
6847 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006848
6849 if (list_empty(&ioc->raid_device_list))
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306850 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006851
6852 handle = 0xFFFF;
6853 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
6854 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
6855 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6856 MPI2_IOCSTATUS_MASK;
6857 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6858 break;
6859 handle = le16_to_cpu(volume_pg1.DevHandle);
Kashyap, Desaid417d1c2010-06-17 13:48:10 +05306860
6861 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
6862 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
6863 sizeof(Mpi2RaidVolPage0_t)))
6864 continue;
6865
6866 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
6867 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
6868 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
6869 _scsih_mark_responding_raid_device(ioc,
6870 le64_to_cpu(volume_pg1.WWID), handle);
Eric Moore635374e2009-03-09 01:21:12 -06006871 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306872
6873 /* refresh the pd_handles */
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306874 if (!ioc->is_warpdrive) {
6875 phys_disk_num = 0xFF;
6876 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
6877 while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
6878 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
6879 phys_disk_num))) {
6880 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6881 MPI2_IOCSTATUS_MASK;
6882 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6883 break;
6884 phys_disk_num = pd_pg0.PhysDiskNum;
6885 handle = le16_to_cpu(pd_pg0.DevHandle);
6886 set_bit(handle, ioc->pd_handles);
6887 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306888 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306889out:
6890 printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
6891 "complete\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006892}
6893
6894/**
6895 * _scsih_mark_responding_expander - mark a expander as responding
6896 * @ioc: per adapter object
6897 * @sas_address: sas address
6898 * @handle:
6899 *
6900 * After host reset, find out whether devices are still responding.
6901 * Used in _scsi_remove_unresponsive_expanders.
6902 *
6903 * Return nothing.
6904 */
6905static void
6906_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
6907 u16 handle)
6908{
6909 struct _sas_node *sas_expander;
6910 unsigned long flags;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306911 int i;
Eric Moore635374e2009-03-09 01:21:12 -06006912
6913 spin_lock_irqsave(&ioc->sas_node_lock, flags);
6914 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306915 if (sas_expander->sas_address != sas_address)
6916 continue;
6917 sas_expander->responding = 1;
6918 if (sas_expander->handle == handle)
Eric Moore635374e2009-03-09 01:21:12 -06006919 goto out;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306920 printk(KERN_INFO "\texpander(0x%016llx): handle changed"
6921 " from(0x%04x) to (0x%04x)!!!\n",
6922 (unsigned long long)sas_expander->sas_address,
6923 sas_expander->handle, handle);
6924 sas_expander->handle = handle;
6925 for (i = 0 ; i < sas_expander->num_phys ; i++)
6926 sas_expander->phy[i].handle = handle;
6927 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006928 }
6929 out:
6930 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
6931}
6932
6933/**
6934 * _scsih_search_responding_expanders -
6935 * @ioc: per adapter object
6936 *
6937 * After host reset, find out whether devices are still responding.
6938 * If not remove.
6939 *
6940 * Return nothing.
6941 */
6942static void
6943_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
6944{
6945 Mpi2ExpanderPage0_t expander_pg0;
6946 Mpi2ConfigReply_t mpi_reply;
6947 u16 ioc_status;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05306948 u64 sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06006949 u16 handle;
6950
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306951 printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006952
6953 if (list_empty(&ioc->sas_expander_list))
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306954 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006955
6956 handle = 0xFFFF;
6957 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
6958 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
6959
6960 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6961 MPI2_IOCSTATUS_MASK;
6962 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6963 break;
6964
6965 handle = le16_to_cpu(expander_pg0.DevHandle);
6966 sas_address = le64_to_cpu(expander_pg0.SASAddress);
6967 printk(KERN_INFO "\texpander present: handle(0x%04x), "
6968 "sas_addr(0x%016llx)\n", handle,
6969 (unsigned long long)sas_address);
6970 _scsih_mark_responding_expander(ioc, sas_address, handle);
6971 }
6972
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306973 out:
6974 printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006975}
6976
6977/**
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05306978 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
Eric Moore635374e2009-03-09 01:21:12 -06006979 * @ioc: per adapter object
6980 *
6981 * Return nothing.
6982 */
6983static void
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05306984_scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
Eric Moore635374e2009-03-09 01:21:12 -06006985{
6986 struct _sas_device *sas_device, *sas_device_next;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306987 struct _sas_node *sas_expander, *sas_expander_next;
Eric Moore635374e2009-03-09 01:21:12 -06006988 struct _raid_device *raid_device, *raid_device_next;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306989 struct list_head tmp_list;
6990 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06006991
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306992 printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
6993 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006994
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05306995 /* removing unresponding end devices */
6996 printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n",
6997 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006998 list_for_each_entry_safe(sas_device, sas_device_next,
6999 &ioc->sas_device_list, list) {
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307000 if (!sas_device->responding)
7001 _scsih_device_remove_by_handle(ioc,
7002 sas_device->handle);
7003 else
Eric Moore635374e2009-03-09 01:21:12 -06007004 sas_device->responding = 0;
Eric Moore635374e2009-03-09 01:21:12 -06007005 }
7006
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307007 /* removing unresponding volumes */
7008 if (ioc->ir_firmware) {
7009 printk(MPT2SAS_INFO_FMT "removing unresponding devices: "
7010 "volumes\n", ioc->name);
7011 list_for_each_entry_safe(raid_device, raid_device_next,
7012 &ioc->raid_device_list, list) {
7013 if (!raid_device->responding)
7014 _scsih_sas_volume_delete(ioc,
7015 raid_device->handle);
7016 else
7017 raid_device->responding = 0;
Eric Moore635374e2009-03-09 01:21:12 -06007018 }
Eric Moore635374e2009-03-09 01:21:12 -06007019 }
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307020 /* removing unresponding expanders */
7021 printk(MPT2SAS_INFO_FMT "removing unresponding devices: expanders\n",
7022 ioc->name);
7023 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7024 INIT_LIST_HEAD(&tmp_list);
7025 list_for_each_entry_safe(sas_expander, sas_expander_next,
7026 &ioc->sas_expander_list, list) {
7027 if (!sas_expander->responding)
7028 list_move_tail(&sas_expander->list, &tmp_list);
7029 else
Eric Moore635374e2009-03-09 01:21:12 -06007030 sas_expander->responding = 0;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307031 }
7032 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7033 list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
7034 list) {
7035 list_del(&sas_expander->list);
7036 _scsih_expander_node_remove(ioc, sas_expander);
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307037 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307038 printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
7039 ioc->name);
7040 /* unblock devices */
7041 _scsih_ublock_io_all_device(ioc);
7042}
7043
7044static void
7045_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
7046 struct _sas_node *sas_expander, u16 handle)
7047{
7048 Mpi2ExpanderPage1_t expander_pg1;
7049 Mpi2ConfigReply_t mpi_reply;
7050 int i;
7051
7052 for (i = 0 ; i < sas_expander->num_phys ; i++) {
7053 if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
7054 &expander_pg1, i, handle))) {
7055 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7056 ioc->name, __FILE__, __LINE__, __func__);
7057 return;
7058 }
7059
7060 mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
7061 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
7062 expander_pg1.NegotiatedLinkRate >> 4);
7063 }
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307064}
7065
7066/**
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307067 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307068 * @ioc: per adapter object
7069 *
7070 * Return nothing.
7071 */
7072static void
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307073_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307074{
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307075 Mpi2ExpanderPage0_t expander_pg0;
7076 Mpi2SasDevicePage0_t sas_device_pg0;
7077 Mpi2RaidVolPage1_t volume_pg1;
7078 Mpi2RaidVolPage0_t volume_pg0;
7079 Mpi2RaidPhysDiskPage0_t pd_pg0;
7080 Mpi2EventIrConfigElement_t element;
7081 Mpi2ConfigReply_t mpi_reply;
7082 u8 phys_disk_num;
7083 u16 ioc_status;
7084 u16 handle, parent_handle;
7085 u64 sas_address;
7086 struct _sas_device *sas_device;
7087 struct _sas_node *expander_device;
7088 static struct _raid_device *raid_device;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307089 unsigned long flags;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307090
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307091 printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307092
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307093 _scsih_sas_host_refresh(ioc);
7094
7095 /* expanders */
7096 handle = 0xFFFF;
7097 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7098 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7099 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7100 MPI2_IOCSTATUS_MASK;
7101 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7102 break;
7103 handle = le16_to_cpu(expander_pg0.DevHandle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307104 spin_lock_irqsave(&ioc->sas_node_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307105 expander_device = mpt2sas_scsih_expander_find_by_sas_address(
7106 ioc, le64_to_cpu(expander_pg0.SASAddress));
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307107 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307108 if (expander_device)
7109 _scsih_refresh_expander_links(ioc, expander_device,
7110 handle);
7111 else
7112 _scsih_expander_add(ioc, handle);
7113 }
7114
7115 if (!ioc->ir_firmware)
7116 goto skip_to_sas;
7117
7118 /* phys disk */
7119 phys_disk_num = 0xFF;
7120 while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7121 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7122 phys_disk_num))) {
7123 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7124 MPI2_IOCSTATUS_MASK;
7125 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7126 break;
7127 phys_disk_num = pd_pg0.PhysDiskNum;
7128 handle = le16_to_cpu(pd_pg0.DevHandle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307129 spin_lock_irqsave(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307130 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307131 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307132 if (sas_device)
7133 continue;
7134 if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7135 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
7136 handle) != 0)
7137 continue;
7138 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7139 if (!_scsih_get_sas_address(ioc, parent_handle,
7140 &sas_address)) {
7141 mpt2sas_transport_update_links(ioc, sas_address,
7142 handle, sas_device_pg0.PhyNum,
7143 MPI2_SAS_NEG_LINK_RATE_1_5);
7144 set_bit(handle, ioc->pd_handles);
7145 _scsih_add_device(ioc, handle, 0, 1);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307146 }
7147 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307148
7149 /* volumes */
7150 handle = 0xFFFF;
7151 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7152 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7153 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7154 MPI2_IOCSTATUS_MASK;
7155 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7156 break;
7157 handle = le16_to_cpu(volume_pg1.DevHandle);
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307158 spin_lock_irqsave(&ioc->raid_device_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307159 raid_device = _scsih_raid_device_find_by_wwid(ioc,
7160 le64_to_cpu(volume_pg1.WWID));
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307161 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307162 if (raid_device)
7163 continue;
7164 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7165 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7166 sizeof(Mpi2RaidVolPage0_t)))
7167 continue;
7168 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7169 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7170 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
7171 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
7172 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
7173 element.VolDevHandle = volume_pg1.DevHandle;
7174 _scsih_sas_volume_add(ioc, &element);
7175 }
7176 }
7177
7178 skip_to_sas:
7179
7180 /* sas devices */
7181 handle = 0xFFFF;
7182 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7183 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7184 handle))) {
7185 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7186 MPI2_IOCSTATUS_MASK;
7187 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7188 break;
7189 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7190 if (!(_scsih_is_end_device(
7191 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7192 continue;
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307193 spin_lock_irqsave(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307194 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
7195 le64_to_cpu(sas_device_pg0.SASAddress));
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307196 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307197 if (sas_device)
7198 continue;
7199 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7200 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7201 mpt2sas_transport_update_links(ioc, sas_address, handle,
7202 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7203 _scsih_add_device(ioc, handle, 0, 0);
7204 }
7205 }
7206
7207 printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307208}
7209
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307210
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307211/**
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307212 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
7213 * @ioc: per adapter object
7214 * @reset_phase: phase
7215 *
7216 * The handler for doing any required cleanup or initialization.
7217 *
7218 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
7219 * MPT2_IOC_DONE_RESET
7220 *
7221 * Return nothing.
7222 */
7223void
7224mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
7225{
7226 switch (reset_phase) {
7227 case MPT2_IOC_PRE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05307228 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307229 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307230 break;
7231 case MPT2_IOC_AFTER_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05307232 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307233 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307234 if (ioc->scsih_cmds.status & MPT2_CMD_PENDING) {
7235 ioc->scsih_cmds.status |= MPT2_CMD_RESET;
7236 mpt2sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
7237 complete(&ioc->scsih_cmds.done);
7238 }
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307239 if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
7240 ioc->tm_cmds.status |= MPT2_CMD_RESET;
7241 mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
7242 complete(&ioc->tm_cmds.done);
7243 }
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307244 _scsih_fw_event_cleanup_queue(ioc);
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307245 _scsih_flush_running_cmds(ioc);
7246 break;
7247 case MPT2_IOC_DONE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05307248 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307249 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307250 _scsih_sas_host_refresh(ioc);
Kashyap, Desai14695852010-03-30 10:52:44 +05307251 _scsih_prep_device_scan(ioc);
7252 _scsih_search_responding_sas_devices(ioc);
7253 _scsih_search_responding_raid_devices(ioc);
7254 _scsih_search_responding_expanders(ioc);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05307255 if (!ioc->is_driver_loading) {
7256 _scsih_prep_device_scan(ioc);
7257 _scsih_search_responding_sas_devices(ioc);
7258 _scsih_search_responding_raid_devices(ioc);
7259 _scsih_search_responding_expanders(ioc);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307260 _scsih_error_recovery_delete_devices(ioc);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05307261 }
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307262 break;
Eric Moore635374e2009-03-09 01:21:12 -06007263 }
7264}
7265
7266/**
7267 * _firmware_event_work - delayed task for processing firmware events
7268 * @ioc: per adapter object
7269 * @work: equal to the fw_event_work object
7270 * Context: user.
7271 *
7272 * Return nothing.
7273 */
7274static void
7275_firmware_event_work(struct work_struct *work)
7276{
7277 struct fw_event_work *fw_event = container_of(work,
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307278 struct fw_event_work, delayed_work.work);
Eric Moore635374e2009-03-09 01:21:12 -06007279 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
7280
Eric Moore635374e2009-03-09 01:21:12 -06007281 /* the queue is being flushed so ignore this event */
Eric Moore3cb54692010-07-08 14:44:34 -06007282 if (ioc->remove_host || fw_event->cancel_pending_work ||
7283 ioc->pci_error_recovery) {
Eric Moore635374e2009-03-09 01:21:12 -06007284 _scsih_fw_event_free(ioc, fw_event);
7285 return;
7286 }
Eric Moore635374e2009-03-09 01:21:12 -06007287
Eric Moore635374e2009-03-09 01:21:12 -06007288 switch (fw_event->event) {
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307289 case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307290 while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307291 ssleep(1);
7292 _scsih_remove_unresponding_sas_devices(ioc);
7293 _scsih_scan_for_devices_after_reset(ioc);
7294 break;
7295 case MPT2SAS_PORT_ENABLE_COMPLETE:
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05307296 ioc->start_scan = 0;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307297
7298
7299
7300 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
7301 "from worker thread\n", ioc->name));
7302 break;
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05307303 case MPT2SAS_TURN_ON_FAULT_LED:
7304 _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
7305 break;
Eric Moore635374e2009-03-09 01:21:12 -06007306 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307307 _scsih_sas_topology_change_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007308 break;
7309 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307310 _scsih_sas_device_status_change_event(ioc,
7311 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007312 break;
7313 case MPI2_EVENT_SAS_DISCOVERY:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307314 _scsih_sas_discovery_event(ioc,
7315 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007316 break;
7317 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
Andrew Mortona78e21d2012-02-08 12:52:22 -08007318 _scsih_sas_broadcast_primitive_event(ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307319 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007320 break;
7321 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7322 _scsih_sas_enclosure_dev_status_change_event(ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307323 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007324 break;
7325 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307326 _scsih_sas_ir_config_change_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007327 break;
7328 case MPI2_EVENT_IR_VOLUME:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307329 _scsih_sas_ir_volume_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007330 break;
7331 case MPI2_EVENT_IR_PHYSICAL_DISK:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307332 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007333 break;
7334 case MPI2_EVENT_IR_OPERATION_STATUS:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307335 _scsih_sas_ir_operation_status_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007336 break;
Eric Moore635374e2009-03-09 01:21:12 -06007337 }
7338 _scsih_fw_event_free(ioc, fw_event);
7339}
7340
7341/**
7342 * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
7343 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307344 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -06007345 * @reply: reply message frame(lower 32bit addr)
7346 * Context: interrupt.
7347 *
7348 * This function merely adds a new work task into ioc->firmware_event_thread.
7349 * The tasks are worked from _firmware_event_work in user context.
7350 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307351 * Return 1 meaning mf should be freed from _base_interrupt
7352 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -06007353 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307354u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307355mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
7356 u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -06007357{
7358 struct fw_event_work *fw_event;
7359 Mpi2EventNotificationReply_t *mpi_reply;
Eric Moore635374e2009-03-09 01:21:12 -06007360 u16 event;
Kashyap, Desaie94f6742010-03-17 16:24:52 +05307361 u16 sz;
Eric Moore635374e2009-03-09 01:21:12 -06007362
7363 /* events turned off due to host reset or driver unloading */
Eric Moore3cb54692010-07-08 14:44:34 -06007364 if (ioc->remove_host || ioc->pci_error_recovery)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307365 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007366
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307367 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
nagalakshmi.nandigama@lsi.com298c7942012-03-20 12:07:17 +05307368
7369 if (unlikely(!mpi_reply)) {
7370 printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
7371 ioc->name, __FILE__, __LINE__, __func__);
7372 return 1;
7373 }
7374
Eric Moore635374e2009-03-09 01:21:12 -06007375 event = le16_to_cpu(mpi_reply->Event);
7376
7377 switch (event) {
7378 /* handle these */
7379 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7380 {
7381 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7382 (Mpi2EventDataSasBroadcastPrimitive_t *)
7383 mpi_reply->EventData;
7384
7385 if (baen_data->Primitive !=
Kashyap, Desaif93213d2011-06-14 10:56:43 +05307386 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307387 return 1;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05307388
7389 if (ioc->broadcast_aen_busy) {
7390 ioc->broadcast_aen_pending++;
7391 return 1;
7392 } else
7393 ioc->broadcast_aen_busy = 1;
Eric Moore635374e2009-03-09 01:21:12 -06007394 break;
7395 }
7396
7397 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7398 _scsih_check_topo_delete_events(ioc,
7399 (Mpi2EventDataSasTopologyChangeList_t *)
7400 mpi_reply->EventData);
7401 break;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05307402 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7403 _scsih_check_ir_config_unhide_events(ioc,
7404 (Mpi2EventDataIrConfigChangeList_t *)
7405 mpi_reply->EventData);
7406 break;
7407 case MPI2_EVENT_IR_VOLUME:
7408 _scsih_check_volume_delete_events(ioc,
7409 (Mpi2EventDataIrVolume_t *)
7410 mpi_reply->EventData);
7411 break;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307412 case MPI2_EVENT_LOG_ENTRY_ADDED:
7413 {
7414 Mpi2EventDataLogEntryAdded_t *log_entry;
nagalakshmi.nandigama@lsi.comd838c362012-03-20 12:07:48 +05307415 __le32 *log_code;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307416
7417 if (!ioc->is_warpdrive)
7418 break;
7419
7420 log_entry = (Mpi2EventDataLogEntryAdded_t *)
7421 mpi_reply->EventData;
nagalakshmi.nandigama@lsi.comd838c362012-03-20 12:07:48 +05307422 log_code = (__le32 *)log_entry->LogData;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307423
7424 if (le16_to_cpu(log_entry->LogEntryQualifier)
7425 != MPT2_WARPDRIVE_LOGENTRY)
7426 break;
7427
7428 switch (le32_to_cpu(*log_code)) {
7429 case MPT2_WARPDRIVE_LC_SSDT:
7430 printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
7431 "IO Throttling has occurred in the WarpDrive "
7432 "subsystem. Check WarpDrive documentation for "
7433 "additional details.\n", ioc->name);
7434 break;
7435 case MPT2_WARPDRIVE_LC_SSDLW:
7436 printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
7437 "Program/Erase Cycles for the WarpDrive subsystem "
7438 "in degraded range. Check WarpDrive documentation "
7439 "for additional details.\n", ioc->name);
7440 break;
7441 case MPT2_WARPDRIVE_LC_SSDLF:
7442 printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
7443 "There are no Program/Erase Cycles for the "
7444 "WarpDrive subsystem. The storage device will be "
7445 "in read-only mode. Check WarpDrive documentation "
7446 "for additional details.\n", ioc->name);
7447 break;
7448 case MPT2_WARPDRIVE_LC_BRMF:
7449 printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
7450 "The Backup Rail Monitor has failed on the "
7451 "WarpDrive subsystem. Check WarpDrive "
7452 "documentation for additional details.\n",
7453 ioc->name);
7454 break;
7455 }
7456
7457 break;
7458 }
Eric Moore635374e2009-03-09 01:21:12 -06007459 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7460 case MPI2_EVENT_IR_OPERATION_STATUS:
7461 case MPI2_EVENT_SAS_DISCOVERY:
7462 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
Eric Moore635374e2009-03-09 01:21:12 -06007463 case MPI2_EVENT_IR_PHYSICAL_DISK:
Eric Moore635374e2009-03-09 01:21:12 -06007464 break;
7465
7466 default: /* ignore the rest */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307467 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007468 }
7469
7470 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
7471 if (!fw_event) {
7472 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7473 ioc->name, __FILE__, __LINE__, __func__);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307474 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007475 }
Kashyap, Desaie94f6742010-03-17 16:24:52 +05307476 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
7477 fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
Eric Moore635374e2009-03-09 01:21:12 -06007478 if (!fw_event->event_data) {
7479 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7480 ioc->name, __FILE__, __LINE__, __func__);
7481 kfree(fw_event);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307482 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007483 }
7484
7485 memcpy(fw_event->event_data, mpi_reply->EventData,
Kashyap, Desaie94f6742010-03-17 16:24:52 +05307486 sz);
Eric Moore635374e2009-03-09 01:21:12 -06007487 fw_event->ioc = ioc;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307488 fw_event->VF_ID = mpi_reply->VF_ID;
7489 fw_event->VP_ID = mpi_reply->VP_ID;
Eric Moore635374e2009-03-09 01:21:12 -06007490 fw_event->event = event;
7491 _scsih_fw_event_add(ioc, fw_event);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307492 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007493}
7494
7495/* shost template */
7496static struct scsi_host_template scsih_driver_template = {
7497 .module = THIS_MODULE,
7498 .name = "Fusion MPT SAS Host",
7499 .proc_name = MPT2SAS_DRIVER_NAME,
Eric Moored5d135b2009-05-18 13:02:08 -06007500 .queuecommand = _scsih_qcmd,
7501 .target_alloc = _scsih_target_alloc,
7502 .slave_alloc = _scsih_slave_alloc,
7503 .slave_configure = _scsih_slave_configure,
7504 .target_destroy = _scsih_target_destroy,
7505 .slave_destroy = _scsih_slave_destroy,
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307506 .scan_finished = _scsih_scan_finished,
7507 .scan_start = _scsih_scan_start,
Eric Moored5d135b2009-05-18 13:02:08 -06007508 .change_queue_depth = _scsih_change_queue_depth,
7509 .change_queue_type = _scsih_change_queue_type,
7510 .eh_abort_handler = _scsih_abort,
7511 .eh_device_reset_handler = _scsih_dev_reset,
7512 .eh_target_reset_handler = _scsih_target_reset,
7513 .eh_host_reset_handler = _scsih_host_reset,
7514 .bios_param = _scsih_bios_param,
Eric Moore635374e2009-03-09 01:21:12 -06007515 .can_queue = 1,
7516 .this_id = -1,
7517 .sg_tablesize = MPT2SAS_SG_DEPTH,
nagalakshmi.nandigama@lsi.com9ac49d32011-12-01 07:52:08 +05307518 .max_sectors = 32767,
Eric Moore635374e2009-03-09 01:21:12 -06007519 .cmd_per_lun = 7,
7520 .use_clustering = ENABLE_CLUSTERING,
7521 .shost_attrs = mpt2sas_host_attrs,
7522 .sdev_attrs = mpt2sas_dev_attrs,
7523};
7524
7525/**
7526 * _scsih_expander_node_remove - removing expander device from list.
7527 * @ioc: per adapter object
7528 * @sas_expander: the sas_device object
7529 * Context: Calling function should acquire ioc->sas_node_lock.
7530 *
7531 * Removing object and freeing associated memory from the
7532 * ioc->sas_expander_list.
7533 *
7534 * Return nothing.
7535 */
7536static void
7537_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
7538 struct _sas_node *sas_expander)
7539{
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307540 struct _sas_port *mpt2sas_port, *next;
Eric Moore635374e2009-03-09 01:21:12 -06007541
7542 /* remove sibling ports attached to this expander */
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307543 list_for_each_entry_safe(mpt2sas_port, next,
Eric Moore635374e2009-03-09 01:21:12 -06007544 &sas_expander->sas_port_list, port_list) {
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307545 if (ioc->shost_recovery)
7546 return;
Eric Moore635374e2009-03-09 01:21:12 -06007547 if (mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307548 SAS_END_DEVICE)
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307549 mpt2sas_device_remove_by_sas_address(ioc,
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307550 mpt2sas_port->remote_identify.sas_address);
7551 else if (mpt2sas_port->remote_identify.device_type ==
7552 SAS_EDGE_EXPANDER_DEVICE ||
Eric Moore635374e2009-03-09 01:21:12 -06007553 mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307554 SAS_FANOUT_EXPANDER_DEVICE)
7555 mpt2sas_expander_remove(ioc,
7556 mpt2sas_port->remote_identify.sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06007557 }
7558
7559 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307560 sas_expander->sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06007561
7562 printk(MPT2SAS_INFO_FMT "expander_remove: handle"
7563 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7564 sas_expander->handle, (unsigned long long)
7565 sas_expander->sas_address);
7566
Eric Moore635374e2009-03-09 01:21:12 -06007567 kfree(sas_expander->phy);
7568 kfree(sas_expander);
7569}
7570
7571/**
Kashyap, Desai744090d2009-10-05 15:56:56 +05307572 * _scsih_ir_shutdown - IR shutdown notification
7573 * @ioc: per adapter object
7574 *
7575 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
7576 * the host system is shutting down.
7577 *
7578 * Return nothing.
7579 */
7580static void
7581_scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
7582{
7583 Mpi2RaidActionRequest_t *mpi_request;
7584 Mpi2RaidActionReply_t *mpi_reply;
7585 u16 smid;
7586
7587 /* is IR firmware build loaded ? */
7588 if (!ioc->ir_firmware)
7589 return;
7590
7591 /* are there any volumes ? */
7592 if (list_empty(&ioc->raid_device_list))
7593 return;
7594
7595 mutex_lock(&ioc->scsih_cmds.mutex);
7596
7597 if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) {
7598 printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n",
7599 ioc->name, __func__);
7600 goto out;
7601 }
7602 ioc->scsih_cmds.status = MPT2_CMD_PENDING;
7603
7604 smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx);
7605 if (!smid) {
7606 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
7607 ioc->name, __func__);
7608 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
7609 goto out;
7610 }
7611
7612 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
7613 ioc->scsih_cmds.smid = smid;
7614 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
7615
7616 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
7617 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
7618
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307619 if (!ioc->hide_ir_msg)
7620 printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
Kashyap, Desai744090d2009-10-05 15:56:56 +05307621 init_completion(&ioc->scsih_cmds.done);
7622 mpt2sas_base_put_smid_default(ioc, smid);
7623 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
7624
7625 if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) {
7626 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
7627 ioc->name, __func__);
7628 goto out;
7629 }
7630
7631 if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
7632 mpi_reply = ioc->scsih_cmds.reply;
7633
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307634 if (!ioc->hide_ir_msg)
7635 printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
7636 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7637 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
7638 le32_to_cpu(mpi_reply->IOCLogInfo));
Kashyap, Desai744090d2009-10-05 15:56:56 +05307639 }
7640
7641 out:
7642 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
7643 mutex_unlock(&ioc->scsih_cmds.mutex);
7644}
7645
7646/**
7647 * _scsih_shutdown - routine call during system shutdown
7648 * @pdev: PCI device struct
7649 *
7650 * Return nothing.
7651 */
7652static void
7653_scsih_shutdown(struct pci_dev *pdev)
7654{
7655 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7656 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307657 struct workqueue_struct *wq;
7658 unsigned long flags;
7659
7660 ioc->remove_host = 1;
7661 _scsih_fw_event_cleanup_queue(ioc);
7662
7663 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7664 wq = ioc->firmware_event_thread;
7665 ioc->firmware_event_thread = NULL;
7666 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7667 if (wq)
7668 destroy_workqueue(wq);
Kashyap, Desai744090d2009-10-05 15:56:56 +05307669
7670 _scsih_ir_shutdown(ioc);
7671 mpt2sas_base_detach(ioc);
7672}
7673
7674/**
Eric Moored5d135b2009-05-18 13:02:08 -06007675 * _scsih_remove - detach and remove add host
Eric Moore635374e2009-03-09 01:21:12 -06007676 * @pdev: PCI device struct
7677 *
Kashyap, Desai744090d2009-10-05 15:56:56 +05307678 * Routine called when unloading the driver.
Eric Moore635374e2009-03-09 01:21:12 -06007679 * Return nothing.
7680 */
7681static void __devexit
Eric Moored5d135b2009-05-18 13:02:08 -06007682_scsih_remove(struct pci_dev *pdev)
Eric Moore635374e2009-03-09 01:21:12 -06007683{
7684 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7685 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307686 struct _sas_port *mpt2sas_port, *next_port;
Kashyap, Desaid7384b22009-12-16 18:50:06 +05307687 struct _raid_device *raid_device, *next;
7688 struct MPT2SAS_TARGET *sas_target_priv_data;
Eric Moore635374e2009-03-09 01:21:12 -06007689 struct workqueue_struct *wq;
7690 unsigned long flags;
7691
7692 ioc->remove_host = 1;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307693 _scsih_fw_event_cleanup_queue(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007694
7695 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7696 wq = ioc->firmware_event_thread;
7697 ioc->firmware_event_thread = NULL;
7698 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7699 if (wq)
7700 destroy_workqueue(wq);
7701
Kashyap, Desaid7384b22009-12-16 18:50:06 +05307702 /* release all the volumes */
Kashyap, Desai3a9c9132011-01-04 11:40:23 +05307703 _scsih_ir_shutdown(ioc);
Kashyap, Desaid7384b22009-12-16 18:50:06 +05307704 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
7705 list) {
7706 if (raid_device->starget) {
7707 sas_target_priv_data =
7708 raid_device->starget->hostdata;
7709 sas_target_priv_data->deleted = 1;
7710 scsi_remove_target(&raid_device->starget->dev);
7711 }
7712 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
7713 "(0x%016llx)\n", ioc->name, raid_device->handle,
7714 (unsigned long long) raid_device->wwid);
7715 _scsih_raid_device_remove(ioc, raid_device);
7716 }
7717
Eric Moore635374e2009-03-09 01:21:12 -06007718 /* free ports attached to the sas_host */
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307719 list_for_each_entry_safe(mpt2sas_port, next_port,
Eric Moore635374e2009-03-09 01:21:12 -06007720 &ioc->sas_hba.sas_port_list, port_list) {
7721 if (mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307722 SAS_END_DEVICE)
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307723 mpt2sas_device_remove_by_sas_address(ioc,
Eric Moore635374e2009-03-09 01:21:12 -06007724 mpt2sas_port->remote_identify.sas_address);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307725 else if (mpt2sas_port->remote_identify.device_type ==
7726 SAS_EDGE_EXPANDER_DEVICE ||
7727 mpt2sas_port->remote_identify.device_type ==
7728 SAS_FANOUT_EXPANDER_DEVICE)
7729 mpt2sas_expander_remove(ioc,
7730 mpt2sas_port->remote_identify.sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06007731 }
7732
7733 /* free phys attached to the sas_host */
7734 if (ioc->sas_hba.num_phys) {
7735 kfree(ioc->sas_hba.phy);
7736 ioc->sas_hba.phy = NULL;
7737 ioc->sas_hba.num_phys = 0;
7738 }
7739
7740 sas_remove_host(shost);
kashyap.desai@lsi.com9ae89b02011-08-04 16:47:50 +05307741 mpt2sas_base_detach(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007742 list_del(&ioc->list);
7743 scsi_remove_host(shost);
7744 scsi_host_put(shost);
7745}
7746
7747/**
7748 * _scsih_probe_boot_devices - reports 1st device
7749 * @ioc: per adapter object
7750 *
7751 * If specified in bios page 2, this routine reports the 1st
7752 * device scsi-ml or sas transport for persistent boot device
7753 * purposes. Please refer to function _scsih_determine_boot_device()
7754 */
7755static void
7756_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
7757{
7758 u8 is_raid;
7759 void *device;
7760 struct _sas_device *sas_device;
7761 struct _raid_device *raid_device;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307762 u16 handle;
7763 u64 sas_address_parent;
Eric Moore635374e2009-03-09 01:21:12 -06007764 u64 sas_address;
7765 unsigned long flags;
7766 int rc;
7767
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307768 /* no Bios, return immediately */
7769 if (!ioc->bios_pg3.BiosVersion)
7770 return;
7771
Eric Moore635374e2009-03-09 01:21:12 -06007772 device = NULL;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307773 is_raid = 0;
Eric Moore635374e2009-03-09 01:21:12 -06007774 if (ioc->req_boot_device.device) {
7775 device = ioc->req_boot_device.device;
7776 is_raid = ioc->req_boot_device.is_raid;
7777 } else if (ioc->req_alt_boot_device.device) {
7778 device = ioc->req_alt_boot_device.device;
7779 is_raid = ioc->req_alt_boot_device.is_raid;
7780 } else if (ioc->current_boot_device.device) {
7781 device = ioc->current_boot_device.device;
7782 is_raid = ioc->current_boot_device.is_raid;
7783 }
7784
7785 if (!device)
7786 return;
7787
7788 if (is_raid) {
7789 raid_device = device;
7790 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
7791 raid_device->id, 0);
7792 if (rc)
7793 _scsih_raid_device_remove(ioc, raid_device);
7794 } else {
nagalakshmi.nandigama@lsi.com09da0b32012-03-20 12:06:50 +05307795 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06007796 sas_device = device;
7797 handle = sas_device->handle;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307798 sas_address_parent = sas_device->sas_address_parent;
Eric Moore635374e2009-03-09 01:21:12 -06007799 sas_address = sas_device->sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06007800 list_move_tail(&sas_device->list, &ioc->sas_device_list);
7801 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307802
7803 if (ioc->hide_drives)
7804 return;
Eric Moore635374e2009-03-09 01:21:12 -06007805 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307806 sas_device->sas_address_parent)) {
Eric Moore635374e2009-03-09 01:21:12 -06007807 _scsih_sas_device_remove(ioc, sas_device);
7808 } else if (!sas_device->starget) {
nagalakshmi.nandigama@lsi.com35116db2011-10-21 10:08:07 +05307809 if (!ioc->is_driver_loading)
7810 mpt2sas_transport_port_remove(ioc, sas_address,
7811 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06007812 _scsih_sas_device_remove(ioc, sas_device);
7813 }
7814 }
7815}
7816
7817/**
7818 * _scsih_probe_raid - reporting raid volumes to scsi-ml
7819 * @ioc: per adapter object
7820 *
7821 * Called during initial loading of the driver.
7822 */
7823static void
7824_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
7825{
7826 struct _raid_device *raid_device, *raid_next;
7827 int rc;
7828
7829 list_for_each_entry_safe(raid_device, raid_next,
7830 &ioc->raid_device_list, list) {
7831 if (raid_device->starget)
7832 continue;
7833 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
7834 raid_device->id, 0);
7835 if (rc)
7836 _scsih_raid_device_remove(ioc, raid_device);
7837 }
7838}
7839
7840/**
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307841 * _scsih_probe_sas - reporting sas devices to sas transport
Eric Moore635374e2009-03-09 01:21:12 -06007842 * @ioc: per adapter object
7843 *
7844 * Called during initial loading of the driver.
7845 */
7846static void
7847_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
7848{
7849 struct _sas_device *sas_device, *next;
7850 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06007851
7852 /* SAS Device List */
7853 list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
7854 list) {
Eric Moore635374e2009-03-09 01:21:12 -06007855
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307856 if (ioc->hide_drives)
7857 continue;
7858
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307859 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
7860 sas_device->sas_address_parent)) {
nagalakshmi.nandigama@lsi.com0167ac62011-10-21 10:06:33 +05307861 list_del(&sas_device->list);
7862 kfree(sas_device);
7863 continue;
Eric Moore635374e2009-03-09 01:21:12 -06007864 } else if (!sas_device->starget) {
nagalakshmi.nandigama@lsi.com35116db2011-10-21 10:08:07 +05307865 if (!ioc->is_driver_loading)
7866 mpt2sas_transport_port_remove(ioc,
7867 sas_device->sas_address,
7868 sas_device->sas_address_parent);
nagalakshmi.nandigama@lsi.com0167ac62011-10-21 10:06:33 +05307869 list_del(&sas_device->list);
7870 kfree(sas_device);
7871 continue;
7872
Eric Moore635374e2009-03-09 01:21:12 -06007873 }
nagalakshmi.nandigama@lsi.com0167ac62011-10-21 10:06:33 +05307874 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7875 list_move_tail(&sas_device->list, &ioc->sas_device_list);
7876 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06007877 }
7878}
7879
7880/**
7881 * _scsih_probe_devices - probing for devices
7882 * @ioc: per adapter object
7883 *
7884 * Called during initial loading of the driver.
7885 */
7886static void
7887_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
7888{
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307889 u16 volume_mapping_flags;
Eric Moore635374e2009-03-09 01:21:12 -06007890
7891 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
7892 return; /* return when IOC doesn't support initiator mode */
7893
7894 _scsih_probe_boot_devices(ioc);
7895
7896 if (ioc->ir_firmware) {
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307897 volume_mapping_flags =
7898 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
7899 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
7900 if (volume_mapping_flags ==
7901 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
Eric Moore635374e2009-03-09 01:21:12 -06007902 _scsih_probe_raid(ioc);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307903 _scsih_probe_sas(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007904 } else {
Eric Moore635374e2009-03-09 01:21:12 -06007905 _scsih_probe_sas(ioc);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307906 _scsih_probe_raid(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007907 }
7908 } else
7909 _scsih_probe_sas(ioc);
7910}
7911
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307912
7913/**
7914 * _scsih_scan_start - scsi lld callback for .scan_start
7915 * @shost: SCSI host pointer
7916 *
7917 * The shost has the ability to discover targets on its own instead
7918 * of scanning the entire bus. In our implemention, we will kick off
7919 * firmware discovery.
7920 */
7921static void
7922_scsih_scan_start(struct Scsi_Host *shost)
7923{
7924 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
7925 int rc;
7926
7927 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
7928 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
7929
7930 ioc->start_scan = 1;
7931 rc = mpt2sas_port_enable(ioc);
7932
7933 if (rc != 0)
7934 printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
7935}
7936
7937/**
7938 * _scsih_scan_finished - scsi lld callback for .scan_finished
7939 * @shost: SCSI host pointer
7940 * @time: elapsed time of the scan in jiffies
7941 *
7942 * This function will be called periodically until it returns 1 with the
7943 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
7944 * we wait for firmware discovery to complete, then return 1.
7945 */
7946static int
7947_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
7948{
7949 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
7950
7951 if (time >= (300 * HZ)) {
7952 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
7953 printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
7954 "(timeout=300s)\n", ioc->name);
7955 ioc->is_driver_loading = 0;
7956 return 1;
7957 }
7958
7959 if (ioc->start_scan)
7960 return 0;
7961
7962 if (ioc->start_scan_failed) {
7963 printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
7964 "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
7965 ioc->is_driver_loading = 0;
7966 ioc->wait_for_discovery_to_complete = 0;
7967 ioc->remove_host = 1;
7968 return 1;
7969 }
7970
7971 printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
7972 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
7973
7974 if (ioc->wait_for_discovery_to_complete) {
7975 ioc->wait_for_discovery_to_complete = 0;
7976 _scsih_probe_devices(ioc);
7977 }
7978 mpt2sas_base_start_watchdog(ioc);
7979 ioc->is_driver_loading = 0;
7980 return 1;
7981}
7982
7983
Eric Moore635374e2009-03-09 01:21:12 -06007984/**
Eric Moored5d135b2009-05-18 13:02:08 -06007985 * _scsih_probe - attach and add scsi host
Eric Moore635374e2009-03-09 01:21:12 -06007986 * @pdev: PCI device struct
7987 * @id: pci device id
7988 *
7989 * Returns 0 success, anything else error.
7990 */
7991static int
Eric Moored5d135b2009-05-18 13:02:08 -06007992_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
Eric Moore635374e2009-03-09 01:21:12 -06007993{
7994 struct MPT2SAS_ADAPTER *ioc;
7995 struct Scsi_Host *shost;
7996
7997 shost = scsi_host_alloc(&scsih_driver_template,
7998 sizeof(struct MPT2SAS_ADAPTER));
7999 if (!shost)
8000 return -ENODEV;
8001
8002 /* init local params */
8003 ioc = shost_priv(shost);
8004 memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER));
8005 INIT_LIST_HEAD(&ioc->list);
Eric Mooreba33fad2009-03-15 21:37:18 -06008006 list_add_tail(&ioc->list, &mpt2sas_ioc_list);
Eric Moore635374e2009-03-09 01:21:12 -06008007 ioc->shost = shost;
8008 ioc->id = mpt_ids++;
8009 sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
8010 ioc->pdev = pdev;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05308011 if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) {
8012 ioc->is_warpdrive = 1;
8013 ioc->hide_ir_msg = 1;
8014 } else
8015 ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
Eric Moore635374e2009-03-09 01:21:12 -06008016 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
8017 ioc->tm_cb_idx = tm_cb_idx;
8018 ioc->ctl_cb_idx = ctl_cb_idx;
8019 ioc->base_cb_idx = base_cb_idx;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308020 ioc->port_enable_cb_idx = port_enable_cb_idx;
Eric Moore635374e2009-03-09 01:21:12 -06008021 ioc->transport_cb_idx = transport_cb_idx;
Kashyap, Desai744090d2009-10-05 15:56:56 +05308022 ioc->scsih_cb_idx = scsih_cb_idx;
Eric Moore635374e2009-03-09 01:21:12 -06008023 ioc->config_cb_idx = config_cb_idx;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308024 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05308025 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308026 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
Eric Moore635374e2009-03-09 01:21:12 -06008027 ioc->logging_level = logging_level;
nagalakshmi.nandigama@lsi.com845a0e42011-12-01 07:42:04 +05308028 ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
Eric Moore635374e2009-03-09 01:21:12 -06008029 /* misc semaphores and spin locks */
Kashyap, Desaid2742132010-06-17 13:28:55 +05308030 mutex_init(&ioc->reset_in_progress_mutex);
Eric Moore635374e2009-03-09 01:21:12 -06008031 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
8032 spin_lock_init(&ioc->scsi_lookup_lock);
8033 spin_lock_init(&ioc->sas_device_lock);
8034 spin_lock_init(&ioc->sas_node_lock);
8035 spin_lock_init(&ioc->fw_event_lock);
8036 spin_lock_init(&ioc->raid_device_lock);
8037
8038 INIT_LIST_HEAD(&ioc->sas_device_list);
8039 INIT_LIST_HEAD(&ioc->sas_device_init_list);
8040 INIT_LIST_HEAD(&ioc->sas_expander_list);
8041 INIT_LIST_HEAD(&ioc->fw_event_list);
8042 INIT_LIST_HEAD(&ioc->raid_device_list);
8043 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308044 INIT_LIST_HEAD(&ioc->delayed_tr_list);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05308045 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
Eric Moore635374e2009-03-09 01:21:12 -06008046
8047 /* init shost parameters */
Eric Moored334aa72010-04-22 10:47:40 -06008048 shost->max_cmd_len = 32;
Eric Moore635374e2009-03-09 01:21:12 -06008049 shost->max_lun = max_lun;
8050 shost->transportt = mpt2sas_transport_template;
8051 shost->unique_id = ioc->id;
8052
Kashyap, Desaia3e1e552011-06-14 10:56:12 +05308053 if (max_sectors != 0xFFFF) {
8054 if (max_sectors < 64) {
8055 shost->max_sectors = 64;
8056 printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
8057 "for max_sectors, range is 64 to 8192. Assigning "
8058 "value of 64.\n", ioc->name, max_sectors);
nagalakshmi.nandigama@lsi.com9ac49d32011-12-01 07:52:08 +05308059 } else if (max_sectors > 32767) {
8060 shost->max_sectors = 32767;
Kashyap, Desaia3e1e552011-06-14 10:56:12 +05308061 printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
8062 "for max_sectors, range is 64 to 8192. Assigning "
nagalakshmi.nandigama@lsi.com9ac49d32011-12-01 07:52:08 +05308063 "default value of 32767.\n", ioc->name,
Kashyap, Desaia3e1e552011-06-14 10:56:12 +05308064 max_sectors);
8065 } else {
8066 shost->max_sectors = max_sectors & 0xFFFE;
8067 printk(MPT2SAS_INFO_FMT "The max_sectors value is "
8068 "set to %d\n", ioc->name, shost->max_sectors);
8069 }
8070 }
8071
Eric Moore635374e2009-03-09 01:21:12 -06008072 if ((scsi_add_host(shost, &pdev->dev))) {
8073 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
8074 ioc->name, __FILE__, __LINE__, __func__);
8075 list_del(&ioc->list);
8076 goto out_add_shost_fail;
8077 }
8078
Eric Moore3c621b32009-05-18 12:59:41 -06008079 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
Eric Moored334aa72010-04-22 10:47:40 -06008080 | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308081 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
Eric Moore3c621b32009-05-18 12:59:41 -06008082
Eric Moore635374e2009-03-09 01:21:12 -06008083 /* event thread */
8084 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
8085 "fw_event%d", ioc->id);
8086 ioc->firmware_event_thread = create_singlethread_workqueue(
8087 ioc->firmware_event_name);
8088 if (!ioc->firmware_event_thread) {
8089 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
8090 ioc->name, __FILE__, __LINE__, __func__);
8091 goto out_thread_fail;
8092 }
8093
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308094 ioc->is_driver_loading = 1;
Eric Moore635374e2009-03-09 01:21:12 -06008095 if ((mpt2sas_base_attach(ioc))) {
8096 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
8097 ioc->name, __FILE__, __LINE__, __func__);
8098 goto out_attach_fail;
8099 }
8100
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05308101 if (ioc->is_warpdrive) {
8102 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
8103 ioc->hide_drives = 0;
8104 else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
8105 ioc->hide_drives = 1;
8106 else {
8107 if (_scsih_get_num_volumes(ioc))
8108 ioc->hide_drives = 1;
8109 else
8110 ioc->hide_drives = 0;
8111 }
8112 } else
8113 ioc->hide_drives = 0;
nagalakshmi.nandigama@lsi.com2cb6fc82011-12-13 09:29:15 +05308114 scsi_scan_host(shost);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05308115
Eric Moore635374e2009-03-09 01:21:12 -06008116 return 0;
8117
8118 out_attach_fail:
8119 destroy_workqueue(ioc->firmware_event_thread);
8120 out_thread_fail:
8121 list_del(&ioc->list);
8122 scsi_remove_host(shost);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308123 scsi_host_put(shost);
Eric Moore635374e2009-03-09 01:21:12 -06008124 out_add_shost_fail:
8125 return -ENODEV;
8126}
8127
8128#ifdef CONFIG_PM
8129/**
Eric Moored5d135b2009-05-18 13:02:08 -06008130 * _scsih_suspend - power management suspend main entry point
Eric Moore635374e2009-03-09 01:21:12 -06008131 * @pdev: PCI device struct
8132 * @state: PM state change to (usually PCI_D3)
8133 *
8134 * Returns 0 success, anything else error.
8135 */
8136static int
Eric Moored5d135b2009-05-18 13:02:08 -06008137_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
Eric Moore635374e2009-03-09 01:21:12 -06008138{
8139 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8140 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desaic97951e2011-06-14 10:54:56 +05308141 pci_power_t device_state;
Eric Moore635374e2009-03-09 01:21:12 -06008142
Kashyap, Desaie4750c92009-08-07 19:37:59 +05308143 mpt2sas_base_stop_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06008144 scsi_block_requests(shost);
8145 device_state = pci_choose_state(pdev, state);
8146 printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
8147 "operating state [D%d]\n", ioc->name, pdev,
8148 pci_name(pdev), device_state);
8149
8150 mpt2sas_base_free_resources(ioc);
8151 pci_save_state(pdev);
8152 pci_disable_device(pdev);
8153 pci_set_power_state(pdev, device_state);
8154 return 0;
8155}
8156
8157/**
Eric Moored5d135b2009-05-18 13:02:08 -06008158 * _scsih_resume - power management resume main entry point
Eric Moore635374e2009-03-09 01:21:12 -06008159 * @pdev: PCI device struct
8160 *
8161 * Returns 0 success, anything else error.
8162 */
8163static int
Eric Moored5d135b2009-05-18 13:02:08 -06008164_scsih_resume(struct pci_dev *pdev)
Eric Moore635374e2009-03-09 01:21:12 -06008165{
8166 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8167 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desaic97951e2011-06-14 10:54:56 +05308168 pci_power_t device_state = pdev->current_state;
Eric Moore635374e2009-03-09 01:21:12 -06008169 int r;
8170
8171 printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
8172 "operating state [D%d]\n", ioc->name, pdev,
8173 pci_name(pdev), device_state);
8174
8175 pci_set_power_state(pdev, PCI_D0);
8176 pci_enable_wake(pdev, PCI_D0, 0);
8177 pci_restore_state(pdev);
8178 ioc->pdev = pdev;
8179 r = mpt2sas_base_map_resources(ioc);
8180 if (r)
8181 return r;
8182
8183 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
8184 scsi_unblock_requests(shost);
Kashyap, Desaie4750c92009-08-07 19:37:59 +05308185 mpt2sas_base_start_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06008186 return 0;
8187}
8188#endif /* CONFIG_PM */
8189
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308190/**
8191 * _scsih_pci_error_detected - Called when a PCI error is detected.
8192 * @pdev: PCI device struct
8193 * @state: PCI channel state
8194 *
8195 * Description: Called when a PCI error is detected.
8196 *
8197 * Return value:
8198 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
8199 */
8200static pci_ers_result_t
8201_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
8202{
8203 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8204 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8205
8206 printk(MPT2SAS_INFO_FMT "PCI error: detected callback, state(%d)!!\n",
8207 ioc->name, state);
8208
8209 switch (state) {
8210 case pci_channel_io_normal:
8211 return PCI_ERS_RESULT_CAN_RECOVER;
8212 case pci_channel_io_frozen:
Eric Moore3cb54692010-07-08 14:44:34 -06008213 /* Fatal error, prepare for slot reset */
8214 ioc->pci_error_recovery = 1;
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308215 scsi_block_requests(ioc->shost);
8216 mpt2sas_base_stop_watchdog(ioc);
8217 mpt2sas_base_free_resources(ioc);
8218 return PCI_ERS_RESULT_NEED_RESET;
8219 case pci_channel_io_perm_failure:
Eric Moore3cb54692010-07-08 14:44:34 -06008220 /* Permanent error, prepare for device removal */
8221 ioc->pci_error_recovery = 1;
8222 mpt2sas_base_stop_watchdog(ioc);
8223 _scsih_flush_running_cmds(ioc);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308224 return PCI_ERS_RESULT_DISCONNECT;
8225 }
8226 return PCI_ERS_RESULT_NEED_RESET;
8227}
8228
8229/**
8230 * _scsih_pci_slot_reset - Called when PCI slot has been reset.
8231 * @pdev: PCI device struct
8232 *
8233 * Description: This routine is called by the pci error recovery
8234 * code after the PCI slot has been reset, just before we
8235 * should resume normal operations.
8236 */
8237static pci_ers_result_t
8238_scsih_pci_slot_reset(struct pci_dev *pdev)
8239{
8240 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8241 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8242 int rc;
8243
8244 printk(MPT2SAS_INFO_FMT "PCI error: slot reset callback!!\n",
8245 ioc->name);
8246
Eric Moore3cb54692010-07-08 14:44:34 -06008247 ioc->pci_error_recovery = 0;
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308248 ioc->pdev = pdev;
Eric Moore3cb54692010-07-08 14:44:34 -06008249 pci_restore_state(pdev);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308250 rc = mpt2sas_base_map_resources(ioc);
8251 if (rc)
8252 return PCI_ERS_RESULT_DISCONNECT;
8253
8254
8255 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
8256 FORCE_BIG_HAMMER);
8257
8258 printk(MPT2SAS_WARN_FMT "hard reset: %s\n", ioc->name,
8259 (rc == 0) ? "success" : "failed");
8260
8261 if (!rc)
8262 return PCI_ERS_RESULT_RECOVERED;
8263 else
8264 return PCI_ERS_RESULT_DISCONNECT;
8265}
8266
8267/**
8268 * _scsih_pci_resume() - resume normal ops after PCI reset
8269 * @pdev: pointer to PCI device
8270 *
8271 * Called when the error recovery driver tells us that its
8272 * OK to resume normal operation. Use completion to allow
8273 * halted scsi ops to resume.
8274 */
8275static void
8276_scsih_pci_resume(struct pci_dev *pdev)
8277{
8278 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8279 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8280
8281 printk(MPT2SAS_INFO_FMT "PCI error: resume callback!!\n", ioc->name);
8282
8283 pci_cleanup_aer_uncorrect_error_status(pdev);
8284 mpt2sas_base_start_watchdog(ioc);
8285 scsi_unblock_requests(ioc->shost);
8286}
8287
8288/**
8289 * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
8290 * @pdev: pointer to PCI device
8291 */
8292static pci_ers_result_t
8293_scsih_pci_mmio_enabled(struct pci_dev *pdev)
8294{
8295 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8296 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8297
8298 printk(MPT2SAS_INFO_FMT "PCI error: mmio enabled callback!!\n",
8299 ioc->name);
8300
8301 /* TODO - dump whatever for debugging purposes */
8302
8303 /* Request a slot reset. */
8304 return PCI_ERS_RESULT_NEED_RESET;
8305}
8306
8307static struct pci_error_handlers _scsih_err_handler = {
8308 .error_detected = _scsih_pci_error_detected,
8309 .mmio_enabled = _scsih_pci_mmio_enabled,
8310 .slot_reset = _scsih_pci_slot_reset,
8311 .resume = _scsih_pci_resume,
8312};
Eric Moore635374e2009-03-09 01:21:12 -06008313
8314static struct pci_driver scsih_driver = {
8315 .name = MPT2SAS_DRIVER_NAME,
8316 .id_table = scsih_pci_table,
Eric Moored5d135b2009-05-18 13:02:08 -06008317 .probe = _scsih_probe,
8318 .remove = __devexit_p(_scsih_remove),
Kashyap, Desai744090d2009-10-05 15:56:56 +05308319 .shutdown = _scsih_shutdown,
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308320 .err_handler = &_scsih_err_handler,
Eric Moore635374e2009-03-09 01:21:12 -06008321#ifdef CONFIG_PM
Eric Moored5d135b2009-05-18 13:02:08 -06008322 .suspend = _scsih_suspend,
8323 .resume = _scsih_resume,
Eric Moore635374e2009-03-09 01:21:12 -06008324#endif
8325};
8326
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308327/* raid transport support */
8328static struct raid_function_template mpt2sas_raid_functions = {
8329 .cookie = &scsih_driver_template,
8330 .is_raid = _scsih_is_raid,
8331 .get_resync = _scsih_get_resync,
8332 .get_state = _scsih_get_state,
8333};
Eric Moore635374e2009-03-09 01:21:12 -06008334
8335/**
Eric Moored5d135b2009-05-18 13:02:08 -06008336 * _scsih_init - main entry point for this driver.
Eric Moore635374e2009-03-09 01:21:12 -06008337 *
8338 * Returns 0 success, anything else error.
8339 */
8340static int __init
Eric Moored5d135b2009-05-18 13:02:08 -06008341_scsih_init(void)
Eric Moore635374e2009-03-09 01:21:12 -06008342{
8343 int error;
8344
8345 mpt_ids = 0;
8346 printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
8347 MPT2SAS_DRIVER_VERSION);
8348
8349 mpt2sas_transport_template =
8350 sas_attach_transport(&mpt2sas_transport_functions);
8351 if (!mpt2sas_transport_template)
8352 return -ENODEV;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308353 /* raid transport support */
8354 mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions);
8355 if (!mpt2sas_raid_template) {
8356 sas_release_transport(mpt2sas_transport_template);
8357 return -ENODEV;
8358 }
Eric Moore635374e2009-03-09 01:21:12 -06008359
8360 mpt2sas_base_initialize_callback_handler();
8361
8362 /* queuecommand callback hander */
Eric Moored5d135b2009-05-18 13:02:08 -06008363 scsi_io_cb_idx = mpt2sas_base_register_callback_handler(_scsih_io_done);
Eric Moore635374e2009-03-09 01:21:12 -06008364
Uwe Kleine-König65155b32010-06-11 12:17:01 +02008365 /* task management callback handler */
Eric Moored5d135b2009-05-18 13:02:08 -06008366 tm_cb_idx = mpt2sas_base_register_callback_handler(_scsih_tm_done);
Eric Moore635374e2009-03-09 01:21:12 -06008367
8368 /* base internal commands callback handler */
8369 base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308370 port_enable_cb_idx = mpt2sas_base_register_callback_handler(
8371 mpt2sas_port_enable_done);
Eric Moore635374e2009-03-09 01:21:12 -06008372
8373 /* transport internal commands callback handler */
8374 transport_cb_idx = mpt2sas_base_register_callback_handler(
8375 mpt2sas_transport_done);
8376
Kashyap, Desai744090d2009-10-05 15:56:56 +05308377 /* scsih internal commands callback handler */
8378 scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done);
8379
Eric Moore635374e2009-03-09 01:21:12 -06008380 /* configuration page API internal commands callback handler */
8381 config_cb_idx = mpt2sas_base_register_callback_handler(
8382 mpt2sas_config_done);
8383
8384 /* ctl module callback handler */
8385 ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done);
8386
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308387 tm_tr_cb_idx = mpt2sas_base_register_callback_handler(
8388 _scsih_tm_tr_complete);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05308389
8390 tm_tr_volume_cb_idx = mpt2sas_base_register_callback_handler(
8391 _scsih_tm_volume_tr_complete);
8392
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308393 tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler(
8394 _scsih_sas_control_complete);
8395
Eric Moore635374e2009-03-09 01:21:12 -06008396 mpt2sas_ctl_init();
8397
8398 error = pci_register_driver(&scsih_driver);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308399 if (error) {
8400 /* raid transport support */
8401 raid_class_release(mpt2sas_raid_template);
Eric Moore635374e2009-03-09 01:21:12 -06008402 sas_release_transport(mpt2sas_transport_template);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308403 }
Eric Moore635374e2009-03-09 01:21:12 -06008404
8405 return error;
8406}
8407
8408/**
Eric Moored5d135b2009-05-18 13:02:08 -06008409 * _scsih_exit - exit point for this driver (when it is a module).
Eric Moore635374e2009-03-09 01:21:12 -06008410 *
8411 * Returns 0 success, anything else error.
8412 */
8413static void __exit
Eric Moored5d135b2009-05-18 13:02:08 -06008414_scsih_exit(void)
Eric Moore635374e2009-03-09 01:21:12 -06008415{
8416 printk(KERN_INFO "mpt2sas version %s unloading\n",
8417 MPT2SAS_DRIVER_VERSION);
8418
8419 pci_unregister_driver(&scsih_driver);
8420
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308421 mpt2sas_ctl_exit();
8422
Eric Moore635374e2009-03-09 01:21:12 -06008423 mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
8424 mpt2sas_base_release_callback_handler(tm_cb_idx);
8425 mpt2sas_base_release_callback_handler(base_cb_idx);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308426 mpt2sas_base_release_callback_handler(port_enable_cb_idx);
Eric Moore635374e2009-03-09 01:21:12 -06008427 mpt2sas_base_release_callback_handler(transport_cb_idx);
Kashyap, Desai744090d2009-10-05 15:56:56 +05308428 mpt2sas_base_release_callback_handler(scsih_cb_idx);
Eric Moore635374e2009-03-09 01:21:12 -06008429 mpt2sas_base_release_callback_handler(config_cb_idx);
8430 mpt2sas_base_release_callback_handler(ctl_cb_idx);
8431
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308432 mpt2sas_base_release_callback_handler(tm_tr_cb_idx);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05308433 mpt2sas_base_release_callback_handler(tm_tr_volume_cb_idx);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308434 mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx);
8435
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308436 /* raid transport support */
8437 raid_class_release(mpt2sas_raid_template);
8438 sas_release_transport(mpt2sas_transport_template);
8439
Eric Moore635374e2009-03-09 01:21:12 -06008440}
8441
Eric Moored5d135b2009-05-18 13:02:08 -06008442module_init(_scsih_init);
8443module_exit(_scsih_exit);