blob: a8cb57723ff4381a4963de0995cc7c63dd0adb9d [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);
102MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192 default=8192");
103
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);
Kashyap, Desai980ead32010-04-08 17:55:22 +0530582 if (mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
583 sas_device->sas_address)) {
584 list_del(&sas_device->list);
585 kfree(sas_device);
586 }
Eric Moore635374e2009-03-09 01:21:12 -0600587 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
588}
589
590/**
591 * _scsih_sas_device_add - insert sas_device to the list.
592 * @ioc: per adapter object
593 * @sas_device: the sas_device object
594 * Context: This function will acquire ioc->sas_device_lock.
595 *
596 * Adding new object to the ioc->sas_device_list.
597 */
598static void
599_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
600 struct _sas_device *sas_device)
601{
602 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -0600603
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530604 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
Eric Moore635374e2009-03-09 01:21:12 -0600605 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
606 sas_device->handle, (unsigned long long)sas_device->sas_address));
607
608 spin_lock_irqsave(&ioc->sas_device_lock, flags);
609 list_add_tail(&sas_device->list, &ioc->sas_device_list);
610 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
611
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530612 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
613 sas_device->sas_address_parent))
Eric Moore635374e2009-03-09 01:21:12 -0600614 _scsih_sas_device_remove(ioc, sas_device);
Eric Moore635374e2009-03-09 01:21:12 -0600615}
616
617/**
618 * _scsih_sas_device_init_add - insert sas_device to the list.
619 * @ioc: per adapter object
620 * @sas_device: the sas_device object
621 * Context: This function will acquire ioc->sas_device_lock.
622 *
623 * Adding new object at driver load time to the ioc->sas_device_init_list.
624 */
625static void
626_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
627 struct _sas_device *sas_device)
628{
629 unsigned long flags;
630
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530631 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
Eric Moore635374e2009-03-09 01:21:12 -0600632 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
633 sas_device->handle, (unsigned long long)sas_device->sas_address));
634
635 spin_lock_irqsave(&ioc->sas_device_lock, flags);
636 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
637 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
638 _scsih_determine_boot_device(ioc, sas_device, 0);
639}
640
641/**
Eric Moore635374e2009-03-09 01:21:12 -0600642 * _scsih_raid_device_find_by_id - raid device search
643 * @ioc: per adapter object
644 * @id: sas device target id
645 * @channel: sas device channel
646 * Context: Calling function should acquire ioc->raid_device_lock
647 *
648 * This searches for raid_device based on target id, then return raid_device
649 * object.
650 */
651static struct _raid_device *
652_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel)
653{
654 struct _raid_device *raid_device, *r;
655
656 r = NULL;
657 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
658 if (raid_device->id == id && raid_device->channel == channel) {
659 r = raid_device;
660 goto out;
661 }
662 }
663
664 out:
665 return r;
666}
667
668/**
669 * _scsih_raid_device_find_by_handle - raid device search
670 * @ioc: per adapter object
671 * @handle: sas device handle (assigned by firmware)
672 * Context: Calling function should acquire ioc->raid_device_lock
673 *
674 * This searches for raid_device based on handle, then return raid_device
675 * object.
676 */
677static struct _raid_device *
678_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
679{
680 struct _raid_device *raid_device, *r;
681
682 r = NULL;
683 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
684 if (raid_device->handle != handle)
685 continue;
686 r = raid_device;
687 goto out;
688 }
689
690 out:
691 return r;
692}
693
694/**
695 * _scsih_raid_device_find_by_wwid - raid device search
696 * @ioc: per adapter object
697 * @handle: sas device handle (assigned by firmware)
698 * Context: Calling function should acquire ioc->raid_device_lock
699 *
700 * This searches for raid_device based on wwid, then return raid_device
701 * object.
702 */
703static struct _raid_device *
704_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid)
705{
706 struct _raid_device *raid_device, *r;
707
708 r = NULL;
709 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
710 if (raid_device->wwid != wwid)
711 continue;
712 r = raid_device;
713 goto out;
714 }
715
716 out:
717 return r;
718}
719
720/**
721 * _scsih_raid_device_add - add raid_device object
722 * @ioc: per adapter object
723 * @raid_device: raid_device object
724 *
725 * This is added to the raid_device_list link list.
726 */
727static void
728_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
729 struct _raid_device *raid_device)
730{
731 unsigned long flags;
732
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530733 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
Eric Moore635374e2009-03-09 01:21:12 -0600734 "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
735 raid_device->handle, (unsigned long long)raid_device->wwid));
736
737 spin_lock_irqsave(&ioc->raid_device_lock, flags);
738 list_add_tail(&raid_device->list, &ioc->raid_device_list);
739 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
740}
741
742/**
743 * _scsih_raid_device_remove - delete raid_device object
744 * @ioc: per adapter object
745 * @raid_device: raid_device object
746 *
747 * This is removed from the raid_device_list link list.
748 */
749static void
750_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
751 struct _raid_device *raid_device)
752{
753 unsigned long flags;
754
755 spin_lock_irqsave(&ioc->raid_device_lock, flags);
756 list_del(&raid_device->list);
757 memset(raid_device, 0, sizeof(struct _raid_device));
758 kfree(raid_device);
759 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
760}
761
762/**
Kashyap, Desaic5e039b2009-09-23 17:21:29 +0530763 * mpt2sas_scsih_expander_find_by_handle - expander device search
764 * @ioc: per adapter object
765 * @handle: expander handle (assigned by firmware)
766 * Context: Calling function should acquire ioc->sas_device_lock
767 *
768 * This searches for expander device based on handle, then returns the
769 * sas_node object.
770 */
771struct _sas_node *
772mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
773{
774 struct _sas_node *sas_expander, *r;
775
776 r = NULL;
777 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
778 if (sas_expander->handle != handle)
779 continue;
780 r = sas_expander;
781 goto out;
782 }
783 out:
784 return r;
785}
786
787/**
Eric Moore635374e2009-03-09 01:21:12 -0600788 * mpt2sas_scsih_expander_find_by_sas_address - expander device search
789 * @ioc: per adapter object
790 * @sas_address: sas address
791 * Context: Calling function should acquire ioc->sas_node_lock.
792 *
793 * This searches for expander device based on sas_address, then returns the
794 * sas_node object.
795 */
796struct _sas_node *
797mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
798 u64 sas_address)
799{
800 struct _sas_node *sas_expander, *r;
801
802 r = NULL;
803 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
804 if (sas_expander->sas_address != sas_address)
805 continue;
806 r = sas_expander;
807 goto out;
808 }
809 out:
810 return r;
811}
812
813/**
814 * _scsih_expander_node_add - insert expander device to the list.
815 * @ioc: per adapter object
816 * @sas_expander: the sas_device object
817 * Context: This function will acquire ioc->sas_node_lock.
818 *
819 * Adding new object to the ioc->sas_expander_list.
820 *
821 * Return nothing.
822 */
823static void
824_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc,
825 struct _sas_node *sas_expander)
826{
827 unsigned long flags;
828
829 spin_lock_irqsave(&ioc->sas_node_lock, flags);
830 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
831 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
832}
833
834/**
835 * _scsih_is_end_device - determines if device is an end device
836 * @device_info: bitfield providing information about the device.
837 * Context: none
838 *
839 * Returns 1 if end device.
840 */
841static int
842_scsih_is_end_device(u32 device_info)
843{
844 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
845 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
846 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
847 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
848 return 1;
849 else
850 return 0;
851}
852
853/**
Kashyap, Desaiec07a052011-01-05 17:54:32 +0530854 * _scsih_scsi_lookup_get - returns scmd entry
Eric Moore635374e2009-03-09 01:21:12 -0600855 * @ioc: per adapter object
856 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -0600857 *
858 * Returns the smid stored scmd pointer.
859 */
860static struct scsi_cmnd *
861_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
862{
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530863 return ioc->scsi_lookup[smid - 1].scmd;
Eric Moore635374e2009-03-09 01:21:12 -0600864}
865
866/**
Kashyap, Desaiec07a052011-01-05 17:54:32 +0530867 * _scsih_scsi_lookup_get_clear - returns scmd entry
868 * @ioc: per adapter object
869 * @smid: system request message index
870 *
871 * Returns the smid stored scmd pointer.
872 * Then will derefrence the stored scmd pointer.
873 */
874static inline struct scsi_cmnd *
875_scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
876{
877 unsigned long flags;
878 struct scsi_cmnd *scmd;
879
880 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
881 scmd = ioc->scsi_lookup[smid - 1].scmd;
882 ioc->scsi_lookup[smid - 1].scmd = NULL;
883 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
884
885 return scmd;
886}
887
888/**
Eric Moore635374e2009-03-09 01:21:12 -0600889 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
890 * @ioc: per adapter object
891 * @smid: system request message index
892 * @scmd: pointer to scsi command object
893 * Context: This function will acquire ioc->scsi_lookup_lock.
894 *
895 * This will search for a scmd pointer in the scsi_lookup array,
896 * returning the revelent smid. A returned value of zero means invalid.
897 */
898static u16
899_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
900 *scmd)
901{
902 u16 smid;
903 unsigned long flags;
904 int i;
905
906 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
907 smid = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530908 for (i = 0; i < ioc->scsiio_depth; i++) {
Eric Moore635374e2009-03-09 01:21:12 -0600909 if (ioc->scsi_lookup[i].scmd == scmd) {
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530910 smid = ioc->scsi_lookup[i].smid;
Eric Moore635374e2009-03-09 01:21:12 -0600911 goto out;
912 }
913 }
914 out:
915 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
916 return smid;
917}
918
919/**
920 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
921 * @ioc: per adapter object
922 * @id: target id
923 * @channel: channel
924 * Context: This function will acquire ioc->scsi_lookup_lock.
925 *
926 * This will search for a matching channel:id in the scsi_lookup array,
927 * returning 1 if found.
928 */
929static u8
930_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
931 int channel)
932{
933 u8 found;
934 unsigned long flags;
935 int i;
936
937 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
938 found = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530939 for (i = 0 ; i < ioc->scsiio_depth; i++) {
Eric Moore635374e2009-03-09 01:21:12 -0600940 if (ioc->scsi_lookup[i].scmd &&
941 (ioc->scsi_lookup[i].scmd->device->id == id &&
942 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
943 found = 1;
944 goto out;
945 }
946 }
947 out:
948 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
949 return found;
950}
951
952/**
Eric Moore993e0da2009-05-18 13:00:45 -0600953 * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
954 * @ioc: per adapter object
955 * @id: target id
956 * @lun: lun number
957 * @channel: channel
958 * Context: This function will acquire ioc->scsi_lookup_lock.
959 *
960 * This will search for a matching channel:id:lun in the scsi_lookup array,
961 * returning 1 if found.
962 */
963static u8
964_scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
965 unsigned int lun, int channel)
966{
967 u8 found;
968 unsigned long flags;
969 int i;
970
971 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
972 found = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530973 for (i = 0 ; i < ioc->scsiio_depth; i++) {
Eric Moore993e0da2009-05-18 13:00:45 -0600974 if (ioc->scsi_lookup[i].scmd &&
975 (ioc->scsi_lookup[i].scmd->device->id == id &&
976 ioc->scsi_lookup[i].scmd->device->channel == channel &&
977 ioc->scsi_lookup[i].scmd->device->lun == lun)) {
978 found = 1;
979 goto out;
980 }
981 }
982 out:
983 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
984 return found;
985}
986
987/**
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530988 * _scsih_get_chain_buffer_tracker - obtain chain tracker
Eric Moore635374e2009-03-09 01:21:12 -0600989 * @ioc: per adapter object
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530990 * @smid: smid associated to an IO request
Eric Moore635374e2009-03-09 01:21:12 -0600991 *
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530992 * Returns chain tracker(from ioc->free_chain_list)
Eric Moore635374e2009-03-09 01:21:12 -0600993 */
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530994static struct chain_tracker *
995_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
Eric Moore635374e2009-03-09 01:21:12 -0600996{
Kashyap, Desai35f805b2010-11-13 04:34:06 +0530997 struct chain_tracker *chain_req;
998 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -0600999
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301000 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1001 if (list_empty(&ioc->free_chain_list)) {
1002 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1003 printk(MPT2SAS_WARN_FMT "chain buffers not available\n",
1004 ioc->name);
1005 return NULL;
1006 }
1007 chain_req = list_entry(ioc->free_chain_list.next,
1008 struct chain_tracker, tracker_list);
1009 list_del_init(&chain_req->tracker_list);
1010 list_add_tail(&chain_req->tracker_list,
1011 &ioc->scsi_lookup[smid - 1].chain_list);
1012 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1013 return chain_req;
Eric Moore635374e2009-03-09 01:21:12 -06001014}
1015
1016/**
1017 * _scsih_build_scatter_gather - main sg creation routine
1018 * @ioc: per adapter object
1019 * @scmd: scsi command
1020 * @smid: system request message index
1021 * Context: none.
1022 *
1023 * The main routine that builds scatter gather table from a given
1024 * scsi request sent via the .queuecommand main handler.
1025 *
1026 * Returns 0 success, anything else error
1027 */
1028static int
1029_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
1030 struct scsi_cmnd *scmd, u16 smid)
1031{
1032 Mpi2SCSIIORequest_t *mpi_request;
1033 dma_addr_t chain_dma;
1034 struct scatterlist *sg_scmd;
1035 void *sg_local, *chain;
1036 u32 chain_offset;
1037 u32 chain_length;
1038 u32 chain_flags;
FUJITA Tomonoribb789d02010-03-09 11:09:50 +09001039 int sges_left;
Eric Moore635374e2009-03-09 01:21:12 -06001040 u32 sges_in_segment;
1041 u32 sgl_flags;
1042 u32 sgl_flags_last_element;
1043 u32 sgl_flags_end_buffer;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301044 struct chain_tracker *chain_req;
Eric Moore635374e2009-03-09 01:21:12 -06001045
1046 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1047
1048 /* init scatter gather flags */
1049 sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
1050 if (scmd->sc_data_direction == DMA_TO_DEVICE)
1051 sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
1052 sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
1053 << MPI2_SGE_FLAGS_SHIFT;
1054 sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
1055 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
1056 << MPI2_SGE_FLAGS_SHIFT;
1057 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1058
1059 sg_scmd = scsi_sglist(scmd);
1060 sges_left = scsi_dma_map(scmd);
FUJITA Tomonoribb789d02010-03-09 11:09:50 +09001061 if (sges_left < 0) {
Eric Moore635374e2009-03-09 01:21:12 -06001062 sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
1063 " failed: request for %d bytes!\n", scsi_bufflen(scmd));
1064 return -ENOMEM;
1065 }
1066
1067 sg_local = &mpi_request->SGL;
1068 sges_in_segment = ioc->max_sges_in_main_message;
1069 if (sges_left <= sges_in_segment)
1070 goto fill_in_last_segment;
1071
1072 mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
1073 (sges_in_segment * ioc->sge_size))/4;
1074
1075 /* fill in main message segment when there is a chain following */
1076 while (sges_in_segment) {
1077 if (sges_in_segment == 1)
1078 ioc->base_add_sg_single(sg_local,
1079 sgl_flags_last_element | sg_dma_len(sg_scmd),
1080 sg_dma_address(sg_scmd));
1081 else
1082 ioc->base_add_sg_single(sg_local, sgl_flags |
1083 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1084 sg_scmd = sg_next(sg_scmd);
1085 sg_local += ioc->sge_size;
1086 sges_left--;
1087 sges_in_segment--;
1088 }
1089
1090 /* initializing the chain flags and pointers */
1091 chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301092 chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
1093 if (!chain_req)
1094 return -1;
1095 chain = chain_req->chain_buffer;
1096 chain_dma = chain_req->chain_buffer_dma;
Eric Moore635374e2009-03-09 01:21:12 -06001097 do {
1098 sges_in_segment = (sges_left <=
1099 ioc->max_sges_in_chain_message) ? sges_left :
1100 ioc->max_sges_in_chain_message;
1101 chain_offset = (sges_left == sges_in_segment) ?
1102 0 : (sges_in_segment * ioc->sge_size)/4;
1103 chain_length = sges_in_segment * ioc->sge_size;
1104 if (chain_offset) {
1105 chain_offset = chain_offset <<
1106 MPI2_SGE_CHAIN_OFFSET_SHIFT;
1107 chain_length += ioc->sge_size;
1108 }
1109 ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
1110 chain_length, chain_dma);
1111 sg_local = chain;
1112 if (!chain_offset)
1113 goto fill_in_last_segment;
1114
1115 /* fill in chain segments */
1116 while (sges_in_segment) {
1117 if (sges_in_segment == 1)
1118 ioc->base_add_sg_single(sg_local,
1119 sgl_flags_last_element |
1120 sg_dma_len(sg_scmd),
1121 sg_dma_address(sg_scmd));
1122 else
1123 ioc->base_add_sg_single(sg_local, sgl_flags |
1124 sg_dma_len(sg_scmd),
1125 sg_dma_address(sg_scmd));
1126 sg_scmd = sg_next(sg_scmd);
1127 sg_local += ioc->sge_size;
1128 sges_left--;
1129 sges_in_segment--;
1130 }
1131
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301132 chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
1133 if (!chain_req)
1134 return -1;
1135 chain = chain_req->chain_buffer;
1136 chain_dma = chain_req->chain_buffer_dma;
Eric Moore635374e2009-03-09 01:21:12 -06001137 } while (1);
1138
1139
1140 fill_in_last_segment:
1141
1142 /* fill the last segment */
1143 while (sges_left) {
1144 if (sges_left == 1)
1145 ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
1146 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1147 else
1148 ioc->base_add_sg_single(sg_local, sgl_flags |
1149 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1150 sg_scmd = sg_next(sg_scmd);
1151 sg_local += ioc->sge_size;
1152 sges_left--;
1153 }
1154
1155 return 0;
1156}
1157
1158/**
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301159 * _scsih_adjust_queue_depth - setting device queue depth
Eric Moore635374e2009-03-09 01:21:12 -06001160 * @sdev: scsi device struct
1161 * @qdepth: requested queue depth
1162 *
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301163 *
1164 * Returns nothing
Eric Moore635374e2009-03-09 01:21:12 -06001165 */
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301166static void
1167_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
Eric Moore635374e2009-03-09 01:21:12 -06001168{
1169 struct Scsi_Host *shost = sdev->host;
1170 int max_depth;
Kashyap, Desaie0077d62009-09-23 17:30:22 +05301171 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1172 struct MPT2SAS_DEVICE *sas_device_priv_data;
1173 struct MPT2SAS_TARGET *sas_target_priv_data;
1174 struct _sas_device *sas_device;
1175 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06001176
1177 max_depth = shost->can_queue;
Kashyap, Desaie0077d62009-09-23 17:30:22 +05301178
1179 /* limit max device queue for SATA to 32 */
1180 sas_device_priv_data = sdev->hostdata;
1181 if (!sas_device_priv_data)
1182 goto not_sata;
1183 sas_target_priv_data = sas_device_priv_data->sas_target;
1184 if (!sas_target_priv_data)
1185 goto not_sata;
1186 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
1187 goto not_sata;
1188 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1189 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1190 sas_device_priv_data->sas_target->sas_address);
1191 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1192 if (sas_device && sas_device->device_info &
1193 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1194 max_depth = MPT2SAS_SATA_QUEUE_DEPTH;
1195
1196 not_sata:
1197
Eric Moore635374e2009-03-09 01:21:12 -06001198 if (!sdev->tagged_supported)
1199 max_depth = 1;
1200 if (qdepth > max_depth)
1201 qdepth = max_depth;
Kashyap, Desaia93c6b42010-11-13 04:39:11 +05301202 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
1203}
1204
1205/**
1206 * _scsih_change_queue_depth - setting device queue depth
1207 * @sdev: scsi device struct
1208 * @qdepth: requested queue depth
1209 * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
1210 * (see include/scsi/scsi_host.h for definition)
1211 *
1212 * Returns queue depth.
1213 */
1214static int
1215_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1216{
1217 if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
1218 _scsih_adjust_queue_depth(sdev, qdepth);
1219 else if (reason == SCSI_QDEPTH_QFULL)
1220 scsi_track_queue_full(sdev, qdepth);
1221 else
1222 return -EOPNOTSUPP;
Eric Moore635374e2009-03-09 01:21:12 -06001223
1224 if (sdev->inquiry_len > 7)
1225 sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
1226 "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
1227 sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
1228 sdev->ordered_tags, sdev->scsi_level,
1229 (sdev->inquiry[7] & 2) >> 1);
1230
1231 return sdev->queue_depth;
1232}
1233
1234/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301235 * _scsih_change_queue_type - changing device queue tag type
Eric Moore635374e2009-03-09 01:21:12 -06001236 * @sdev: scsi device struct
1237 * @tag_type: requested tag type
1238 *
1239 * Returns queue tag type.
1240 */
1241static int
Eric Moored5d135b2009-05-18 13:02:08 -06001242_scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
Eric Moore635374e2009-03-09 01:21:12 -06001243{
1244 if (sdev->tagged_supported) {
1245 scsi_set_tag_type(sdev, tag_type);
1246 if (tag_type)
1247 scsi_activate_tcq(sdev, sdev->queue_depth);
1248 else
1249 scsi_deactivate_tcq(sdev, sdev->queue_depth);
1250 } else
1251 tag_type = 0;
1252
1253 return tag_type;
1254}
1255
1256/**
Eric Moored5d135b2009-05-18 13:02:08 -06001257 * _scsih_target_alloc - target add routine
Eric Moore635374e2009-03-09 01:21:12 -06001258 * @starget: scsi target struct
1259 *
1260 * Returns 0 if ok. Any other return is assumed to be an error and
1261 * the device is ignored.
1262 */
1263static int
Eric Moored5d135b2009-05-18 13:02:08 -06001264_scsih_target_alloc(struct scsi_target *starget)
Eric Moore635374e2009-03-09 01:21:12 -06001265{
1266 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1267 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1268 struct MPT2SAS_TARGET *sas_target_priv_data;
1269 struct _sas_device *sas_device;
1270 struct _raid_device *raid_device;
1271 unsigned long flags;
1272 struct sas_rphy *rphy;
1273
1274 sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
1275 if (!sas_target_priv_data)
1276 return -ENOMEM;
1277
1278 starget->hostdata = sas_target_priv_data;
1279 sas_target_priv_data->starget = starget;
1280 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
1281
1282 /* RAID volumes */
1283 if (starget->channel == RAID_CHANNEL) {
1284 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1285 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1286 starget->channel);
1287 if (raid_device) {
1288 sas_target_priv_data->handle = raid_device->handle;
1289 sas_target_priv_data->sas_address = raid_device->wwid;
1290 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301291 sas_target_priv_data->raid_device = raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06001292 raid_device->starget = starget;
1293 }
1294 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1295 return 0;
1296 }
1297
1298 /* sas/sata devices */
1299 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1300 rphy = dev_to_rphy(starget->dev.parent);
1301 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1302 rphy->identify.sas_address);
1303
1304 if (sas_device) {
1305 sas_target_priv_data->handle = sas_device->handle;
1306 sas_target_priv_data->sas_address = sas_device->sas_address;
1307 sas_device->starget = starget;
1308 sas_device->id = starget->id;
1309 sas_device->channel = starget->channel;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05301310 if (test_bit(sas_device->handle, ioc->pd_handles))
Eric Moore635374e2009-03-09 01:21:12 -06001311 sas_target_priv_data->flags |=
1312 MPT_TARGET_FLAGS_RAID_COMPONENT;
1313 }
1314 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1315
1316 return 0;
1317}
1318
1319/**
Eric Moored5d135b2009-05-18 13:02:08 -06001320 * _scsih_target_destroy - target destroy routine
Eric Moore635374e2009-03-09 01:21:12 -06001321 * @starget: scsi target struct
1322 *
1323 * Returns nothing.
1324 */
1325static void
Eric Moored5d135b2009-05-18 13:02:08 -06001326_scsih_target_destroy(struct scsi_target *starget)
Eric Moore635374e2009-03-09 01:21:12 -06001327{
1328 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1329 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1330 struct MPT2SAS_TARGET *sas_target_priv_data;
1331 struct _sas_device *sas_device;
1332 struct _raid_device *raid_device;
1333 unsigned long flags;
1334 struct sas_rphy *rphy;
1335
1336 sas_target_priv_data = starget->hostdata;
1337 if (!sas_target_priv_data)
1338 return;
1339
1340 if (starget->channel == RAID_CHANNEL) {
1341 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1342 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1343 starget->channel);
1344 if (raid_device) {
1345 raid_device->starget = NULL;
1346 raid_device->sdev = NULL;
1347 }
1348 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1349 goto out;
1350 }
1351
1352 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1353 rphy = dev_to_rphy(starget->dev.parent);
1354 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1355 rphy->identify.sas_address);
Eric Moore8901cbb2009-04-21 15:41:32 -06001356 if (sas_device && (sas_device->starget == starget) &&
1357 (sas_device->id == starget->id) &&
1358 (sas_device->channel == starget->channel))
Eric Moore635374e2009-03-09 01:21:12 -06001359 sas_device->starget = NULL;
1360
1361 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1362
1363 out:
1364 kfree(sas_target_priv_data);
1365 starget->hostdata = NULL;
1366}
1367
1368/**
Eric Moored5d135b2009-05-18 13:02:08 -06001369 * _scsih_slave_alloc - device add routine
Eric Moore635374e2009-03-09 01:21:12 -06001370 * @sdev: scsi device struct
1371 *
1372 * Returns 0 if ok. Any other return is assumed to be an error and
1373 * the device is ignored.
1374 */
1375static int
Eric Moored5d135b2009-05-18 13:02:08 -06001376_scsih_slave_alloc(struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001377{
1378 struct Scsi_Host *shost;
1379 struct MPT2SAS_ADAPTER *ioc;
1380 struct MPT2SAS_TARGET *sas_target_priv_data;
1381 struct MPT2SAS_DEVICE *sas_device_priv_data;
1382 struct scsi_target *starget;
1383 struct _raid_device *raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06001384 unsigned long flags;
1385
1386 sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
1387 if (!sas_device_priv_data)
1388 return -ENOMEM;
1389
1390 sas_device_priv_data->lun = sdev->lun;
1391 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1392
1393 starget = scsi_target(sdev);
1394 sas_target_priv_data = starget->hostdata;
1395 sas_target_priv_data->num_luns++;
1396 sas_device_priv_data->sas_target = sas_target_priv_data;
1397 sdev->hostdata = sas_device_priv_data;
1398 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1399 sdev->no_uld_attach = 1;
1400
1401 shost = dev_to_shost(&starget->dev);
1402 ioc = shost_priv(shost);
1403 if (starget->channel == RAID_CHANNEL) {
1404 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1405 raid_device = _scsih_raid_device_find_by_id(ioc,
1406 starget->id, starget->channel);
1407 if (raid_device)
1408 raid_device->sdev = sdev; /* raid is single lun */
1409 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06001410 }
1411
Eric Moore635374e2009-03-09 01:21:12 -06001412 return 0;
1413}
1414
1415/**
Eric Moored5d135b2009-05-18 13:02:08 -06001416 * _scsih_slave_destroy - device destroy routine
Eric Moore635374e2009-03-09 01:21:12 -06001417 * @sdev: scsi device struct
1418 *
1419 * Returns nothing.
1420 */
1421static void
Eric Moored5d135b2009-05-18 13:02:08 -06001422_scsih_slave_destroy(struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001423{
1424 struct MPT2SAS_TARGET *sas_target_priv_data;
1425 struct scsi_target *starget;
1426
1427 if (!sdev->hostdata)
1428 return;
1429
1430 starget = scsi_target(sdev);
1431 sas_target_priv_data = starget->hostdata;
1432 sas_target_priv_data->num_luns--;
1433 kfree(sdev->hostdata);
1434 sdev->hostdata = NULL;
1435}
1436
1437/**
Eric Moored5d135b2009-05-18 13:02:08 -06001438 * _scsih_display_sata_capabilities - sata capabilities
Eric Moore635374e2009-03-09 01:21:12 -06001439 * @ioc: per adapter object
1440 * @sas_device: the sas_device object
1441 * @sdev: scsi device struct
1442 */
1443static void
Eric Moored5d135b2009-05-18 13:02:08 -06001444_scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
Eric Moore635374e2009-03-09 01:21:12 -06001445 struct _sas_device *sas_device, struct scsi_device *sdev)
1446{
1447 Mpi2ConfigReply_t mpi_reply;
1448 Mpi2SasDevicePage0_t sas_device_pg0;
1449 u32 ioc_status;
1450 u16 flags;
1451 u32 device_info;
1452
1453 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
1454 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, sas_device->handle))) {
1455 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1456 ioc->name, __FILE__, __LINE__, __func__);
1457 return;
1458 }
1459
1460 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1461 MPI2_IOCSTATUS_MASK;
1462 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1463 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1464 ioc->name, __FILE__, __LINE__, __func__);
1465 return;
1466 }
1467
1468 flags = le16_to_cpu(sas_device_pg0.Flags);
Kashyap, Desaie94f6742010-03-17 16:24:52 +05301469 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
Eric Moore635374e2009-03-09 01:21:12 -06001470
1471 sdev_printk(KERN_INFO, sdev,
1472 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1473 "sw_preserve(%s)\n",
1474 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1475 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1476 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1477 "n",
1478 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1479 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1480 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1481}
1482
1483/**
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301484 * _scsih_is_raid - return boolean indicating device is raid volume
1485 * @dev the device struct object
1486 */
1487static int
1488_scsih_is_raid(struct device *dev)
1489{
1490 struct scsi_device *sdev = to_scsi_device(dev);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301491 struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301492
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301493 if (ioc->is_warpdrive)
1494 return 0;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301495 return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
1496}
1497
1498/**
1499 * _scsih_get_resync - get raid volume resync percent complete
1500 * @dev the device struct object
1501 */
1502static void
1503_scsih_get_resync(struct device *dev)
1504{
1505 struct scsi_device *sdev = to_scsi_device(dev);
1506 struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
1507 static struct _raid_device *raid_device;
1508 unsigned long flags;
1509 Mpi2RaidVolPage0_t vol_pg0;
1510 Mpi2ConfigReply_t mpi_reply;
1511 u32 volume_status_flags;
1512 u8 percent_complete = 0;
1513
1514 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1515 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1516 sdev->channel);
1517 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1518
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301519 if (!raid_device || ioc->is_warpdrive)
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05301520 goto out;
1521
1522 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1523 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle,
1524 sizeof(Mpi2RaidVolPage0_t))) {
1525 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1526 ioc->name, __FILE__, __LINE__, __func__);
1527 goto out;
1528 }
1529
1530 volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1531 if (volume_status_flags & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
1532 percent_complete = raid_device->percent_complete;
1533 out:
1534 raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
1535}
1536
1537/**
1538 * _scsih_get_state - get raid volume level
1539 * @dev the device struct object
1540 */
1541static void
1542_scsih_get_state(struct device *dev)
1543{
1544 struct scsi_device *sdev = to_scsi_device(dev);
1545 struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
1546 static struct _raid_device *raid_device;
1547 unsigned long flags;
1548 Mpi2RaidVolPage0_t vol_pg0;
1549 Mpi2ConfigReply_t mpi_reply;
1550 u32 volstate;
1551 enum raid_state state = RAID_STATE_UNKNOWN;
1552
1553 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1554 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1555 sdev->channel);
1556 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1557
1558 if (!raid_device)
1559 goto out;
1560
1561 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1562 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle,
1563 sizeof(Mpi2RaidVolPage0_t))) {
1564 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1565 ioc->name, __FILE__, __LINE__, __func__);
1566 goto out;
1567 }
1568
1569 volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1570 if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
1571 state = RAID_STATE_RESYNCING;
1572 goto out;
1573 }
1574
1575 switch (vol_pg0.VolumeState) {
1576 case MPI2_RAID_VOL_STATE_OPTIMAL:
1577 case MPI2_RAID_VOL_STATE_ONLINE:
1578 state = RAID_STATE_ACTIVE;
1579 break;
1580 case MPI2_RAID_VOL_STATE_DEGRADED:
1581 state = RAID_STATE_DEGRADED;
1582 break;
1583 case MPI2_RAID_VOL_STATE_FAILED:
1584 case MPI2_RAID_VOL_STATE_MISSING:
1585 state = RAID_STATE_OFFLINE;
1586 break;
1587 }
1588 out:
1589 raid_set_state(mpt2sas_raid_template, dev, state);
1590}
1591
1592/**
1593 * _scsih_set_level - set raid level
1594 * @sdev: scsi device struct
1595 * @raid_device: raid_device object
1596 */
1597static void
1598_scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device)
1599{
1600 enum raid_level level = RAID_LEVEL_UNKNOWN;
1601
1602 switch (raid_device->volume_type) {
1603 case MPI2_RAID_VOL_TYPE_RAID0:
1604 level = RAID_LEVEL_0;
1605 break;
1606 case MPI2_RAID_VOL_TYPE_RAID10:
1607 level = RAID_LEVEL_10;
1608 break;
1609 case MPI2_RAID_VOL_TYPE_RAID1E:
1610 level = RAID_LEVEL_1E;
1611 break;
1612 case MPI2_RAID_VOL_TYPE_RAID1:
1613 level = RAID_LEVEL_1;
1614 break;
1615 }
1616
1617 raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level);
1618}
1619
1620/**
Eric Moore635374e2009-03-09 01:21:12 -06001621 * _scsih_get_volume_capabilities - volume capabilities
1622 * @ioc: per adapter object
1623 * @sas_device: the raid_device object
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301624 *
1625 * Returns 0 for success, else 1
Eric Moore635374e2009-03-09 01:21:12 -06001626 */
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301627static int
Eric Moore635374e2009-03-09 01:21:12 -06001628_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
1629 struct _raid_device *raid_device)
1630{
1631 Mpi2RaidVolPage0_t *vol_pg0;
1632 Mpi2RaidPhysDiskPage0_t pd_pg0;
1633 Mpi2SasDevicePage0_t sas_device_pg0;
1634 Mpi2ConfigReply_t mpi_reply;
1635 u16 sz;
1636 u8 num_pds;
1637
1638 if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
1639 &num_pds)) || !num_pds) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301640 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1641 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1642 __func__));
1643 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001644 }
1645
1646 raid_device->num_pds = num_pds;
1647 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1648 sizeof(Mpi2RaidVol0PhysDisk_t));
1649 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1650 if (!vol_pg0) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301651 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1652 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1653 __func__));
1654 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001655 }
1656
1657 if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1658 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301659 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1660 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1661 __func__));
Eric Moore635374e2009-03-09 01:21:12 -06001662 kfree(vol_pg0);
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301663 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001664 }
1665
1666 raid_device->volume_type = vol_pg0->VolumeType;
1667
1668 /* figure out what the underlying devices are by
1669 * obtaining the device_info bits for the 1st device
1670 */
1671 if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1672 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1673 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1674 if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1675 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1676 le16_to_cpu(pd_pg0.DevHandle)))) {
1677 raid_device->device_info =
1678 le32_to_cpu(sas_device_pg0.DeviceInfo);
1679 }
1680 }
1681
1682 kfree(vol_pg0);
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301683 return 0;
Eric Moore635374e2009-03-09 01:21:12 -06001684}
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301685/**
1686 * _scsih_disable_ddio - Disable direct I/O for all the volumes
1687 * @ioc: per adapter object
1688 */
1689static void
1690_scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
1691{
1692 Mpi2RaidVolPage1_t vol_pg1;
1693 Mpi2ConfigReply_t mpi_reply;
1694 struct _raid_device *raid_device;
1695 u16 handle;
1696 u16 ioc_status;
1697
1698 handle = 0xFFFF;
1699 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1700 &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1701 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1702 MPI2_IOCSTATUS_MASK;
1703 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
1704 break;
1705 handle = le16_to_cpu(vol_pg1.DevHandle);
1706 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
1707 if (raid_device)
1708 raid_device->direct_io_enabled = 0;
1709 }
1710 return;
1711}
1712
1713
1714/**
1715 * _scsih_get_num_volumes - Get number of volumes in the ioc
1716 * @ioc: per adapter object
1717 */
1718static u8
1719_scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc)
1720{
1721 Mpi2RaidVolPage1_t vol_pg1;
1722 Mpi2ConfigReply_t mpi_reply;
1723 u16 handle;
1724 u8 vol_cnt = 0;
1725 u16 ioc_status;
1726
1727 handle = 0xFFFF;
1728 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1729 &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1730 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1731 MPI2_IOCSTATUS_MASK;
1732 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
1733 break;
1734 vol_cnt++;
1735 handle = le16_to_cpu(vol_pg1.DevHandle);
1736 }
1737 return vol_cnt;
1738}
1739
1740
1741/**
1742 * _scsih_init_warpdrive_properties - Set properties for warpdrive direct I/O.
1743 * @ioc: per adapter object
1744 * @raid_device: the raid_device object
1745 */
1746static void
1747_scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
1748 struct _raid_device *raid_device)
1749{
1750 Mpi2RaidVolPage0_t *vol_pg0;
1751 Mpi2RaidPhysDiskPage0_t pd_pg0;
1752 Mpi2ConfigReply_t mpi_reply;
1753 u16 sz;
1754 u8 num_pds, count;
1755 u64 mb = 1024 * 1024;
1756 u64 tb_2 = 2 * mb * mb;
1757 u64 capacity;
1758 u32 stripe_sz;
1759 u8 i, stripe_exp;
1760
1761 if (!ioc->is_warpdrive)
1762 return;
1763
1764 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) {
1765 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1766 "globally as drives are exposed\n", ioc->name);
1767 return;
1768 }
1769 if (_scsih_get_num_volumes(ioc) > 1) {
1770 _scsih_disable_ddio(ioc);
1771 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1772 "globally as number of drives > 1\n", ioc->name);
1773 return;
1774 }
1775 if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
1776 &num_pds)) || !num_pds) {
1777 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1778 "Failure in computing number of drives\n", ioc->name);
1779 return;
1780 }
1781
1782 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1783 sizeof(Mpi2RaidVol0PhysDisk_t));
1784 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1785 if (!vol_pg0) {
1786 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1787 "Memory allocation failure for RVPG0\n", ioc->name);
1788 return;
1789 }
1790
1791 if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1792 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1793 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1794 "Failure in retrieving RVPG0\n", ioc->name);
1795 kfree(vol_pg0);
1796 return;
1797 }
1798
1799 /*
1800 * WARPDRIVE:If number of physical disks in a volume exceeds the max pds
1801 * assumed for WARPDRIVE, disable direct I/O
1802 */
1803 if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
1804 printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled "
1805 "for the drive with handle(0x%04x): num_mem=%d, "
1806 "max_mem_allowed=%d\n", ioc->name, raid_device->handle,
1807 num_pds, MPT_MAX_WARPDRIVE_PDS);
1808 kfree(vol_pg0);
1809 return;
1810 }
1811 for (count = 0; count < num_pds; count++) {
1812 if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1813 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1814 vol_pg0->PhysDisk[count].PhysDiskNum) ||
1815 pd_pg0.DevHandle == MPT2SAS_INVALID_DEVICE_HANDLE) {
1816 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
1817 "disabled for the drive with handle(0x%04x) member"
1818 "handle retrieval failed for member number=%d\n",
1819 ioc->name, raid_device->handle,
1820 vol_pg0->PhysDisk[count].PhysDiskNum);
1821 goto out_error;
1822 }
1823 raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
1824 }
1825
1826 /*
1827 * Assumption for WD: Direct I/O is not supported if the volume is
1828 * not RAID0, if the stripe size is not 64KB, if the block size is
1829 * not 512 and if the volume size is >2TB
1830 */
1831 if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0 ||
1832 le16_to_cpu(vol_pg0->BlockSize) != 512) {
1833 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1834 "for the drive with handle(0x%04x): type=%d, "
1835 "s_sz=%uK, blk_size=%u\n", ioc->name,
1836 raid_device->handle, raid_device->volume_type,
1837 le32_to_cpu(vol_pg0->StripeSize)/2,
1838 le16_to_cpu(vol_pg0->BlockSize));
1839 goto out_error;
1840 }
1841
1842 capacity = (u64) le16_to_cpu(vol_pg0->BlockSize) *
1843 (le64_to_cpu(vol_pg0->MaxLBA) + 1);
1844
1845 if (capacity > tb_2) {
1846 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1847 "for the drive with handle(0x%04x) since drive sz > 2TB\n",
1848 ioc->name, raid_device->handle);
1849 goto out_error;
1850 }
1851
1852 stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
1853 stripe_exp = 0;
1854 for (i = 0; i < 32; i++) {
1855 if (stripe_sz & 1)
1856 break;
1857 stripe_exp++;
1858 stripe_sz >>= 1;
1859 }
1860 if (i == 32) {
1861 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
1862 "for the drive with handle(0x%04x) invalid stripe sz %uK\n",
1863 ioc->name, raid_device->handle,
1864 le32_to_cpu(vol_pg0->StripeSize)/2);
1865 goto out_error;
1866 }
1867 raid_device->stripe_exponent = stripe_exp;
1868 raid_device->direct_io_enabled = 1;
1869
1870 printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive"
1871 " with handle(0x%04x)\n", ioc->name, raid_device->handle);
1872 /*
1873 * WARPDRIVE: Though the following fields are not used for direct IO,
1874 * stored for future purpose:
1875 */
1876 raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
1877 raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
1878 raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
1879
1880
1881 kfree(vol_pg0);
1882 return;
1883
1884out_error:
1885 raid_device->direct_io_enabled = 0;
1886 for (count = 0; count < num_pds; count++)
1887 raid_device->pd_handle[count] = 0;
1888 kfree(vol_pg0);
1889 return;
1890}
Eric Moore635374e2009-03-09 01:21:12 -06001891
1892/**
Kashyap, Desai84f0b042009-12-16 18:56:28 +05301893 * _scsih_enable_tlr - setting TLR flags
1894 * @ioc: per adapter object
1895 * @sdev: scsi device struct
1896 *
1897 * Enabling Transaction Layer Retries for tape devices when
1898 * vpd page 0x90 is present
1899 *
1900 */
1901static void
1902_scsih_enable_tlr(struct MPT2SAS_ADAPTER *ioc, struct scsi_device *sdev)
1903{
1904 /* only for TAPE */
1905 if (sdev->type != TYPE_TAPE)
1906 return;
1907
1908 if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
1909 return;
1910
1911 sas_enable_tlr(sdev);
1912 sdev_printk(KERN_INFO, sdev, "TLR %s\n",
1913 sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
1914 return;
1915
1916}
1917
1918/**
Eric Moored5d135b2009-05-18 13:02:08 -06001919 * _scsih_slave_configure - device configure routine.
Eric Moore635374e2009-03-09 01:21:12 -06001920 * @sdev: scsi device struct
1921 *
1922 * Returns 0 if ok. Any other return is assumed to be an error and
1923 * the device is ignored.
1924 */
1925static int
Eric Moored5d135b2009-05-18 13:02:08 -06001926_scsih_slave_configure(struct scsi_device *sdev)
Eric Moore635374e2009-03-09 01:21:12 -06001927{
1928 struct Scsi_Host *shost = sdev->host;
1929 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1930 struct MPT2SAS_DEVICE *sas_device_priv_data;
1931 struct MPT2SAS_TARGET *sas_target_priv_data;
1932 struct _sas_device *sas_device;
1933 struct _raid_device *raid_device;
1934 unsigned long flags;
1935 int qdepth;
1936 u8 ssp_target = 0;
1937 char *ds = "";
1938 char *r_level = "";
1939
1940 qdepth = 1;
1941 sas_device_priv_data = sdev->hostdata;
1942 sas_device_priv_data->configured_lun = 1;
1943 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1944 sas_target_priv_data = sas_device_priv_data->sas_target;
1945
1946 /* raid volume handling */
1947 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
1948
1949 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1950 raid_device = _scsih_raid_device_find_by_handle(ioc,
1951 sas_target_priv_data->handle);
1952 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1953 if (!raid_device) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301954 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1955 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1956 __LINE__, __func__));
1957 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06001958 }
1959
1960 _scsih_get_volume_capabilities(ioc, raid_device);
1961
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05301962 if (_scsih_get_volume_capabilities(ioc, raid_device)) {
1963 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
1964 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1965 __LINE__, __func__));
1966 return 1;
1967 }
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301968 /*
1969 * WARPDRIVE: Initialize the required data for Direct IO
1970 */
1971 _scsih_init_warpdrive_properties(ioc, raid_device);
1972
Eric Moore635374e2009-03-09 01:21:12 -06001973 /* RAID Queue Depth Support
1974 * IS volume = underlying qdepth of drive type, either
1975 * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
1976 * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH)
1977 */
1978 if (raid_device->device_info &
1979 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1980 qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
1981 ds = "SSP";
1982 } else {
1983 qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
1984 if (raid_device->device_info &
1985 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1986 ds = "SATA";
1987 else
1988 ds = "STP";
1989 }
1990
1991 switch (raid_device->volume_type) {
1992 case MPI2_RAID_VOL_TYPE_RAID0:
1993 r_level = "RAID0";
1994 break;
1995 case MPI2_RAID_VOL_TYPE_RAID1E:
1996 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
Kashyap, Desaied79f122009-08-20 13:23:49 +05301997 if (ioc->manu_pg10.OEMIdentifier &&
Kashyap, Desaic97951e2011-06-14 10:54:56 +05301998 (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
Kashyap, Desaied79f122009-08-20 13:23:49 +05301999 MFG10_GF0_R10_DISPLAY) &&
2000 !(raid_device->num_pds % 2))
2001 r_level = "RAID10";
2002 else
2003 r_level = "RAID1E";
Eric Moore635374e2009-03-09 01:21:12 -06002004 break;
2005 case MPI2_RAID_VOL_TYPE_RAID1:
2006 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
2007 r_level = "RAID1";
2008 break;
2009 case MPI2_RAID_VOL_TYPE_RAID10:
2010 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
2011 r_level = "RAID10";
2012 break;
2013 case MPI2_RAID_VOL_TYPE_UNKNOWN:
2014 default:
2015 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
2016 r_level = "RAIDX";
2017 break;
2018 }
2019
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302020 if (!ioc->hide_ir_msg)
2021 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
2022 "wwid(0x%016llx), pd_count(%d), type(%s)\n",
2023 r_level, raid_device->handle,
2024 (unsigned long long)raid_device->wwid,
2025 raid_device->num_pds, ds);
Mike Christiee881a172009-10-15 17:46:39 -07002026 _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05302027 /* raid transport support */
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302028 if (!ioc->is_warpdrive)
2029 _scsih_set_level(sdev, raid_device);
Eric Moore635374e2009-03-09 01:21:12 -06002030 return 0;
2031 }
2032
2033 /* non-raid handling */
2034 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2035 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
2036 sas_device_priv_data->sas_target->sas_address);
2037 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2038 if (sas_device) {
2039 if (sas_target_priv_data->flags &
2040 MPT_TARGET_FLAGS_RAID_COMPONENT) {
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302041 if (mpt2sas_config_get_volume_handle(ioc,
2042 sas_device->handle, &sas_device->volume_handle)) {
2043 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2044 "failure at %s:%d/%s()!\n", ioc->name,
2045 __FILE__, __LINE__, __func__));
2046 return 1;
2047 }
2048 if (mpt2sas_config_get_volume_wwid(ioc,
Eric Moore635374e2009-03-09 01:21:12 -06002049 sas_device->volume_handle,
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302050 &sas_device->volume_wwid)) {
2051 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2052 "failure at %s:%d/%s()!\n", ioc->name,
2053 __FILE__, __LINE__, __func__));
2054 return 1;
2055 }
Eric Moore635374e2009-03-09 01:21:12 -06002056 }
2057 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
2058 qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
2059 ssp_target = 1;
2060 ds = "SSP";
2061 } else {
2062 qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
2063 if (sas_device->device_info &
2064 MPI2_SAS_DEVICE_INFO_STP_TARGET)
2065 ds = "STP";
2066 else if (sas_device->device_info &
2067 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
2068 ds = "SATA";
2069 }
2070
2071 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
Kashyap, Desai7fbae672010-06-17 13:45:17 +05302072 "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
Eric Moore635374e2009-03-09 01:21:12 -06002073 ds, sas_device->handle,
2074 (unsigned long long)sas_device->sas_address,
Kashyap, Desai7fbae672010-06-17 13:45:17 +05302075 sas_device->phy,
Eric Moore635374e2009-03-09 01:21:12 -06002076 (unsigned long long)sas_device->device_name);
2077 sdev_printk(KERN_INFO, sdev, "%s: "
2078 "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
2079 (unsigned long long) sas_device->enclosure_logical_id,
2080 sas_device->slot);
2081
2082 if (!ssp_target)
Eric Moored5d135b2009-05-18 13:02:08 -06002083 _scsih_display_sata_capabilities(ioc, sas_device, sdev);
nagalakshmi.nandigama@lsi.com6faace22011-10-19 15:37:37 +05302084 } else {
2085 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
2086 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
2087 __func__));
2088 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002089 }
2090
Mike Christiee881a172009-10-15 17:46:39 -07002091 _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
Eric Moore635374e2009-03-09 01:21:12 -06002092
Kashyap, Desai84f0b042009-12-16 18:56:28 +05302093 if (ssp_target) {
Eric Moore635374e2009-03-09 01:21:12 -06002094 sas_read_port_mode_page(sdev);
Kashyap, Desai84f0b042009-12-16 18:56:28 +05302095 _scsih_enable_tlr(ioc, sdev);
2096 }
Eric Moore635374e2009-03-09 01:21:12 -06002097 return 0;
2098}
2099
2100/**
Eric Moored5d135b2009-05-18 13:02:08 -06002101 * _scsih_bios_param - fetch head, sector, cylinder info for a disk
Eric Moore635374e2009-03-09 01:21:12 -06002102 * @sdev: scsi device struct
2103 * @bdev: pointer to block device context
2104 * @capacity: device size (in 512 byte sectors)
2105 * @params: three element array to place output:
2106 * params[0] number of heads (max 255)
2107 * params[1] number of sectors (max 63)
2108 * params[2] number of cylinders
2109 *
2110 * Return nothing.
2111 */
2112static int
Eric Moored5d135b2009-05-18 13:02:08 -06002113_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
Eric Moore635374e2009-03-09 01:21:12 -06002114 sector_t capacity, int params[])
2115{
2116 int heads;
2117 int sectors;
2118 sector_t cylinders;
2119 ulong dummy;
2120
2121 heads = 64;
2122 sectors = 32;
2123
2124 dummy = heads * sectors;
2125 cylinders = capacity;
2126 sector_div(cylinders, dummy);
2127
2128 /*
2129 * Handle extended translation size for logical drives
2130 * > 1Gb
2131 */
2132 if ((ulong)capacity >= 0x200000) {
2133 heads = 255;
2134 sectors = 63;
2135 dummy = heads * sectors;
2136 cylinders = capacity;
2137 sector_div(cylinders, dummy);
2138 }
2139
2140 /* return result */
2141 params[0] = heads;
2142 params[1] = sectors;
2143 params[2] = cylinders;
2144
2145 return 0;
2146}
2147
2148/**
2149 * _scsih_response_code - translation of device response code
2150 * @ioc: per adapter object
2151 * @response_code: response code returned by the device
2152 *
2153 * Return nothing.
2154 */
2155static void
2156_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
2157{
2158 char *desc;
2159
2160 switch (response_code) {
2161 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2162 desc = "task management request completed";
2163 break;
2164 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2165 desc = "invalid frame";
2166 break;
2167 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2168 desc = "task management request not supported";
2169 break;
2170 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2171 desc = "task management request failed";
2172 break;
2173 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2174 desc = "task management request succeeded";
2175 break;
2176 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2177 desc = "invalid lun";
2178 break;
2179 case 0xA:
2180 desc = "overlapped tag attempted";
2181 break;
2182 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2183 desc = "task queued, however not sent to target";
2184 break;
2185 default:
2186 desc = "unknown";
2187 break;
2188 }
2189 printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n",
2190 ioc->name, response_code, desc);
2191}
2192
2193/**
Eric Moored5d135b2009-05-18 13:02:08 -06002194 * _scsih_tm_done - tm completion routine
Eric Moore635374e2009-03-09 01:21:12 -06002195 * @ioc: per adapter object
2196 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302197 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -06002198 * @reply: reply message frame(lower 32bit addr)
2199 * Context: none.
2200 *
2201 * The callback handler when using scsih_issue_tm.
2202 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302203 * Return 1 meaning mf should be freed from _base_interrupt
2204 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -06002205 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302206static u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302207_scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -06002208{
2209 MPI2DefaultReply_t *mpi_reply;
2210
2211 if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302212 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002213 if (ioc->tm_cmds.smid != smid)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302214 return 1;
nagalakshmi.nandigama@lsi.com911ae942011-09-08 06:18:50 +05302215 mpt2sas_base_flush_reply_queues(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06002216 ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
2217 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
2218 if (mpi_reply) {
2219 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
2220 ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID;
2221 }
2222 ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
2223 complete(&ioc->tm_cmds.done);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05302224 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06002225}
2226
2227/**
2228 * mpt2sas_scsih_set_tm_flag - set per target tm_busy
2229 * @ioc: per adapter object
2230 * @handle: device handle
2231 *
2232 * During taskmangement request, we need to freeze the device queue.
2233 */
2234void
2235mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2236{
2237 struct MPT2SAS_DEVICE *sas_device_priv_data;
2238 struct scsi_device *sdev;
2239 u8 skip = 0;
2240
2241 shost_for_each_device(sdev, ioc->shost) {
2242 if (skip)
2243 continue;
2244 sas_device_priv_data = sdev->hostdata;
2245 if (!sas_device_priv_data)
2246 continue;
2247 if (sas_device_priv_data->sas_target->handle == handle) {
2248 sas_device_priv_data->sas_target->tm_busy = 1;
2249 skip = 1;
2250 ioc->ignore_loginfos = 1;
2251 }
2252 }
2253}
2254
2255/**
2256 * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy
2257 * @ioc: per adapter object
2258 * @handle: device handle
2259 *
2260 * During taskmangement request, we need to freeze the device queue.
2261 */
2262void
2263mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2264{
2265 struct MPT2SAS_DEVICE *sas_device_priv_data;
2266 struct scsi_device *sdev;
2267 u8 skip = 0;
2268
2269 shost_for_each_device(sdev, ioc->shost) {
2270 if (skip)
2271 continue;
2272 sas_device_priv_data = sdev->hostdata;
2273 if (!sas_device_priv_data)
2274 continue;
2275 if (sas_device_priv_data->sas_target->handle == handle) {
2276 sas_device_priv_data->sas_target->tm_busy = 0;
2277 skip = 1;
2278 ioc->ignore_loginfos = 0;
2279 }
2280 }
2281}
2282
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302283
Eric Moore635374e2009-03-09 01:21:12 -06002284/**
2285 * mpt2sas_scsih_issue_tm - main routine for sending tm requests
2286 * @ioc: per adapter struct
2287 * @device_handle: device handle
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302288 * @channel: the channel assigned by the OS
2289 * @id: the id assigned by the OS
Eric Moore635374e2009-03-09 01:21:12 -06002290 * @lun: lun number
2291 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2292 * @smid_task: smid assigned to the task
2293 * @timeout: timeout in seconds
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302294 * @serial_number: the serial_number from scmd
2295 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302296 * Context: user
Eric Moore635374e2009-03-09 01:21:12 -06002297 *
2298 * A generic API for sending task management requests to firmware.
2299 *
Eric Moore635374e2009-03-09 01:21:12 -06002300 * The callback index is set inside `ioc->tm_cb_idx`.
2301 *
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302302 * Return SUCCESS or FAILED.
Eric Moore635374e2009-03-09 01:21:12 -06002303 */
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302304int
2305mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2306 uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302307 unsigned long serial_number, enum mutex_type m_type)
Eric Moore635374e2009-03-09 01:21:12 -06002308{
2309 Mpi2SCSITaskManagementRequest_t *mpi_request;
2310 Mpi2SCSITaskManagementReply_t *mpi_reply;
2311 u16 smid = 0;
2312 u32 ioc_state;
2313 unsigned long timeleft;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302314 struct scsiio_tracker *scsi_lookup = NULL;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302315 int rc;
Eric Moore635374e2009-03-09 01:21:12 -06002316
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302317 if (m_type == TM_MUTEX_ON)
2318 mutex_lock(&ioc->tm_cmds.mutex);
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05302319 if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
2320 printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
2321 __func__, ioc->name);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302322 rc = FAILED;
2323 goto err_out;
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05302324 }
2325
Eric Moore3cb54692010-07-08 14:44:34 -06002326 if (ioc->shost_recovery || ioc->remove_host ||
2327 ioc->pci_error_recovery) {
Eric Moore635374e2009-03-09 01:21:12 -06002328 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
2329 __func__, ioc->name);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302330 rc = FAILED;
2331 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002332 }
Eric Moore635374e2009-03-09 01:21:12 -06002333
2334 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
2335 if (ioc_state & MPI2_DOORBELL_USED) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302336 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
Eric Moore635374e2009-03-09 01:21:12 -06002337 "active!\n", ioc->name));
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302338 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302339 FORCE_BIG_HAMMER);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302340 rc = (!rc) ? SUCCESS : FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302341 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002342 }
2343
2344 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2345 mpt2sas_base_fault_info(ioc, ioc_state &
2346 MPI2_DOORBELL_DATA_MASK);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302347 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302348 FORCE_BIG_HAMMER);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302349 rc = (!rc) ? SUCCESS : FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302350 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002351 }
2352
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302353 smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
Eric Moore635374e2009-03-09 01:21:12 -06002354 if (!smid) {
2355 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2356 ioc->name, __func__);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302357 rc = FAILED;
2358 goto err_out;
Eric Moore635374e2009-03-09 01:21:12 -06002359 }
2360
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302361 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2362 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2363
Eric Moore635374e2009-03-09 01:21:12 -06002364 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302365 " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
2366 smid_task));
Eric Moore635374e2009-03-09 01:21:12 -06002367 ioc->tm_cmds.status = MPT2_CMD_PENDING;
2368 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2369 ioc->tm_cmds.smid = smid;
2370 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302371 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
Eric Moore635374e2009-03-09 01:21:12 -06002372 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2373 mpi_request->DevHandle = cpu_to_le16(handle);
2374 mpi_request->TaskType = type;
2375 mpi_request->TaskMID = cpu_to_le16(smid_task);
2376 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
2377 mpt2sas_scsih_set_tm_flag(ioc, handle);
Kashyap, Desai5b768582009-08-20 13:24:31 +05302378 init_completion(&ioc->tm_cmds.done);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302379 mpt2sas_base_put_smid_hi_priority(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06002380 timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
Eric Moore635374e2009-03-09 01:21:12 -06002381 if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
2382 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2383 ioc->name, __func__);
2384 _debug_dump_mf(mpi_request,
2385 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302386 if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
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 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
2391 mpt2sas_scsih_clear_tm_flag(ioc, handle);
2392 goto err_out;
2393 }
Eric Moore635374e2009-03-09 01:21:12 -06002394 }
2395
2396 if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) {
2397 mpi_reply = ioc->tm_cmds.reply;
2398 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: "
2399 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
2400 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
2401 le32_to_cpu(mpi_reply->IOCLogInfo),
2402 le32_to_cpu(mpi_reply->TerminationCount)));
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302403 if (ioc->logging_level & MPT_DEBUG_TM) {
Eric Moore635374e2009-03-09 01:21:12 -06002404 _scsih_response_code(ioc, mpi_reply->ResponseCode);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302405 if (mpi_reply->IOCStatus)
2406 _debug_dump_mf(mpi_request,
2407 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2408 }
Eric Moore635374e2009-03-09 01:21:12 -06002409 }
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302410
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302411 switch (type) {
2412 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302413 rc = SUCCESS;
2414 if (scsi_lookup->scmd == NULL)
2415 break;
2416 rc = FAILED;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302417 break;
2418
2419 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2420 if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
2421 rc = FAILED;
2422 else
2423 rc = SUCCESS;
2424 break;
2425
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302426 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302427 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2428 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2429 rc = FAILED;
2430 else
2431 rc = SUCCESS;
2432 break;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302433 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2434 rc = SUCCESS;
2435 break;
2436 default:
2437 rc = FAILED;
2438 break;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302439 }
2440
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302441 mpt2sas_scsih_clear_tm_flag(ioc, handle);
2442 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302443 if (m_type == TM_MUTEX_ON)
2444 mutex_unlock(&ioc->tm_cmds.mutex);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302445
2446 return rc;
2447
2448 err_out:
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302449 if (m_type == TM_MUTEX_ON)
2450 mutex_unlock(&ioc->tm_cmds.mutex);
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302451 return rc;
Eric Moore635374e2009-03-09 01:21:12 -06002452}
2453
2454/**
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302455 * _scsih_tm_display_info - displays info about the device
2456 * @ioc: per adapter struct
2457 * @scmd: pointer to scsi command object
2458 *
2459 * Called by task management callback handlers.
2460 */
2461static void
2462_scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
2463{
2464 struct scsi_target *starget = scmd->device->sdev_target;
2465 struct MPT2SAS_TARGET *priv_target = starget->hostdata;
2466 struct _sas_device *sas_device = NULL;
2467 unsigned long flags;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302468 char *device_str = NULL;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302469
2470 if (!priv_target)
2471 return;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302472 if (ioc->hide_ir_msg)
2473 device_str = "WarpDrive";
2474 else
2475 device_str = "volume";
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302476
2477 scsi_print_command(scmd);
2478 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05302479 starget_printk(KERN_INFO, starget, "%s handle(0x%04x), "
2480 "%s wwid(0x%016llx)\n", device_str, priv_target->handle,
2481 device_str, (unsigned long long)priv_target->sas_address);
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302482 } else {
2483 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2484 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
2485 priv_target->sas_address);
2486 if (sas_device) {
2487 if (priv_target->flags &
2488 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2489 starget_printk(KERN_INFO, starget,
2490 "volume handle(0x%04x), "
2491 "volume wwid(0x%016llx)\n",
2492 sas_device->volume_handle,
2493 (unsigned long long)sas_device->volume_wwid);
2494 }
2495 starget_printk(KERN_INFO, starget,
2496 "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
2497 sas_device->handle,
2498 (unsigned long long)sas_device->sas_address,
2499 sas_device->phy);
2500 starget_printk(KERN_INFO, starget,
2501 "enclosure_logical_id(0x%016llx), slot(%d)\n",
2502 (unsigned long long)sas_device->enclosure_logical_id,
2503 sas_device->slot);
2504 }
2505 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2506 }
2507}
2508
2509/**
Eric Moored5d135b2009-05-18 13:02:08 -06002510 * _scsih_abort - eh threads main abort routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302511 * @scmd: pointer to scsi command object
Eric Moore635374e2009-03-09 01:21:12 -06002512 *
2513 * Returns SUCCESS if command aborted else FAILED
2514 */
2515static int
Eric Moored5d135b2009-05-18 13:02:08 -06002516_scsih_abort(struct scsi_cmnd *scmd)
Eric Moore635374e2009-03-09 01:21:12 -06002517{
2518 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2519 struct MPT2SAS_DEVICE *sas_device_priv_data;
2520 u16 smid;
2521 u16 handle;
2522 int r;
Eric Moore635374e2009-03-09 01:21:12 -06002523
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302524 sdev_printk(KERN_INFO, scmd->device, "attempting task abort! "
2525 "scmd(%p)\n", scmd);
2526 _scsih_tm_display_info(ioc, scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002527
2528 sas_device_priv_data = scmd->device->hostdata;
2529 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302530 sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
2531 "scmd(%p)\n", scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002532 scmd->result = DID_NO_CONNECT << 16;
2533 scmd->scsi_done(scmd);
2534 r = SUCCESS;
2535 goto out;
2536 }
2537
2538 /* search for the command */
2539 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
2540 if (!smid) {
2541 scmd->result = DID_RESET << 16;
2542 r = SUCCESS;
2543 goto out;
2544 }
2545
2546 /* for hidden raid components and volumes this is not supported */
2547 if (sas_device_priv_data->sas_target->flags &
2548 MPT_TARGET_FLAGS_RAID_COMPONENT ||
2549 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2550 scmd->result = DID_RESET << 16;
2551 r = FAILED;
2552 goto out;
2553 }
2554
Kashyap, Desaifa7f3162009-09-23 17:26:58 +05302555 mpt2sas_halt_firmware(ioc);
2556
Eric Moore635374e2009-03-09 01:21:12 -06002557 handle = sas_device_priv_data->sas_target->handle;
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302558 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2559 scmd->device->id, scmd->device->lun,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302560 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
2561 scmd->serial_number, TM_MUTEX_ON);
Eric Moore635374e2009-03-09 01:21:12 -06002562
2563 out:
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302564 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
2565 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002566 return r;
2567}
2568
Eric Moore635374e2009-03-09 01:21:12 -06002569/**
Eric Moored5d135b2009-05-18 13:02:08 -06002570 * _scsih_dev_reset - eh threads main device reset routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302571 * @scmd: pointer to scsi command object
Eric Moore635374e2009-03-09 01:21:12 -06002572 *
2573 * Returns SUCCESS if command aborted else FAILED
2574 */
2575static int
Eric Moored5d135b2009-05-18 13:02:08 -06002576_scsih_dev_reset(struct scsi_cmnd *scmd)
Eric Moore635374e2009-03-09 01:21:12 -06002577{
2578 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2579 struct MPT2SAS_DEVICE *sas_device_priv_data;
2580 struct _sas_device *sas_device;
2581 unsigned long flags;
2582 u16 handle;
2583 int r;
2584
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302585 struct scsi_target *starget = scmd->device->sdev_target;
2586
Kashyap, Desai37aaa782010-11-13 04:41:32 +05302587 starget_printk(KERN_INFO, starget, "attempting device reset! "
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302588 "scmd(%p)\n", scmd);
2589 _scsih_tm_display_info(ioc, scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002590
2591 sas_device_priv_data = scmd->device->hostdata;
2592 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Kashyap, Desai37aaa782010-11-13 04:41:32 +05302593 starget_printk(KERN_INFO, starget, "device been deleted! "
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302594 "scmd(%p)\n", scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002595 scmd->result = DID_NO_CONNECT << 16;
2596 scmd->scsi_done(scmd);
2597 r = SUCCESS;
2598 goto out;
2599 }
2600
2601 /* for hidden raid components obtain the volume_handle */
2602 handle = 0;
2603 if (sas_device_priv_data->sas_target->flags &
2604 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2605 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2606 sas_device = _scsih_sas_device_find_by_handle(ioc,
2607 sas_device_priv_data->sas_target->handle);
2608 if (sas_device)
2609 handle = sas_device->volume_handle;
2610 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2611 } else
2612 handle = sas_device_priv_data->sas_target->handle;
2613
2614 if (!handle) {
2615 scmd->result = DID_RESET << 16;
2616 r = FAILED;
2617 goto out;
2618 }
2619
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302620 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2621 scmd->device->id, scmd->device->lun,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302622 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
2623 TM_MUTEX_ON);
Eric Moore993e0da2009-05-18 13:00:45 -06002624
2625 out:
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302626 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
2627 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Eric Moore993e0da2009-05-18 13:00:45 -06002628 return r;
2629}
2630
2631/**
Eric Moored5d135b2009-05-18 13:02:08 -06002632 * _scsih_target_reset - eh threads main target reset routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302633 * @scmd: pointer to scsi command object
Eric Moore993e0da2009-05-18 13:00:45 -06002634 *
2635 * Returns SUCCESS if command aborted else FAILED
2636 */
2637static int
Eric Moored5d135b2009-05-18 13:02:08 -06002638_scsih_target_reset(struct scsi_cmnd *scmd)
Eric Moore993e0da2009-05-18 13:00:45 -06002639{
2640 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2641 struct MPT2SAS_DEVICE *sas_device_priv_data;
2642 struct _sas_device *sas_device;
2643 unsigned long flags;
2644 u16 handle;
2645 int r;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302646 struct scsi_target *starget = scmd->device->sdev_target;
Eric Moore993e0da2009-05-18 13:00:45 -06002647
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302648 starget_printk(KERN_INFO, starget, "attempting target reset! "
2649 "scmd(%p)\n", scmd);
2650 _scsih_tm_display_info(ioc, scmd);
Eric Moore993e0da2009-05-18 13:00:45 -06002651
2652 sas_device_priv_data = scmd->device->hostdata;
2653 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302654 starget_printk(KERN_INFO, starget, "target been deleted! "
2655 "scmd(%p)\n", scmd);
Eric Moore993e0da2009-05-18 13:00:45 -06002656 scmd->result = DID_NO_CONNECT << 16;
2657 scmd->scsi_done(scmd);
2658 r = SUCCESS;
2659 goto out;
2660 }
2661
2662 /* for hidden raid components obtain the volume_handle */
2663 handle = 0;
2664 if (sas_device_priv_data->sas_target->flags &
2665 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2666 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2667 sas_device = _scsih_sas_device_find_by_handle(ioc,
2668 sas_device_priv_data->sas_target->handle);
2669 if (sas_device)
2670 handle = sas_device->volume_handle;
2671 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2672 } else
2673 handle = sas_device_priv_data->sas_target->handle;
2674
2675 if (!handle) {
2676 scmd->result = DID_RESET << 16;
2677 r = FAILED;
2678 goto out;
2679 }
2680
Kashyap, Desai8ed9a032010-03-17 16:25:59 +05302681 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2682 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302683 30, 0, TM_MUTEX_ON);
Eric Moore635374e2009-03-09 01:21:12 -06002684
2685 out:
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302686 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
2687 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Eric Moore635374e2009-03-09 01:21:12 -06002688 return r;
2689}
2690
2691/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302692 * _scsih_host_reset - eh threads main host reset routine
Kashyap, Desai8e864a82010-06-17 13:48:46 +05302693 * @scmd: pointer to scsi command object
Eric Moore635374e2009-03-09 01:21:12 -06002694 *
2695 * Returns SUCCESS if command aborted else FAILED
2696 */
2697static int
Eric Moored5d135b2009-05-18 13:02:08 -06002698_scsih_host_reset(struct scsi_cmnd *scmd)
Eric Moore635374e2009-03-09 01:21:12 -06002699{
2700 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2701 int r, retval;
2702
2703 printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n",
2704 ioc->name, scmd);
2705 scsi_print_command(scmd);
2706
2707 retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2708 FORCE_BIG_HAMMER);
2709 r = (retval < 0) ? FAILED : SUCCESS;
2710 printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n",
2711 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2712
2713 return r;
2714}
2715
2716/**
2717 * _scsih_fw_event_add - insert and queue up fw_event
2718 * @ioc: per adapter object
2719 * @fw_event: object describing the event
2720 * Context: This function will acquire ioc->fw_event_lock.
2721 *
2722 * This adds the firmware event object into link list, then queues it up to
2723 * be processed from user context.
2724 *
2725 * Return nothing.
2726 */
2727static void
2728_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2729{
2730 unsigned long flags;
2731
2732 if (ioc->firmware_event_thread == NULL)
2733 return;
2734
2735 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2736 list_add_tail(&fw_event->list, &ioc->fw_event_list);
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302737 INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work);
2738 queue_delayed_work(ioc->firmware_event_thread,
2739 &fw_event->delayed_work, 0);
Eric Moore635374e2009-03-09 01:21:12 -06002740 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2741}
2742
2743/**
2744 * _scsih_fw_event_free - delete fw_event
2745 * @ioc: per adapter object
2746 * @fw_event: object describing the event
2747 * Context: This function will acquire ioc->fw_event_lock.
2748 *
2749 * This removes firmware event object from link list, frees associated memory.
2750 *
2751 * Return nothing.
2752 */
2753static void
2754_scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
2755 *fw_event)
2756{
2757 unsigned long flags;
2758
2759 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2760 list_del(&fw_event->list);
2761 kfree(fw_event->event_data);
2762 kfree(fw_event);
2763 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2764}
2765
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302766
Eric Moore635374e2009-03-09 01:21:12 -06002767/**
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302768 * _scsih_error_recovery_delete_devices - remove devices not responding
Eric Moore635374e2009-03-09 01:21:12 -06002769 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06002770 *
2771 * Return nothing.
2772 */
2773static void
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302774_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
Eric Moore635374e2009-03-09 01:21:12 -06002775{
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302776 struct fw_event_work *fw_event;
2777
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302778 if (ioc->is_driver_loading)
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302779 return;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302780 fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
2781 fw_event->ioc = ioc;
2782 _scsih_fw_event_add(ioc, fw_event);
2783}
2784
2785/**
2786 * mpt2sas_port_enable_complete - port enable completed (fake event)
2787 * @ioc: per adapter object
2788 *
2789 * Return nothing.
2790 */
2791void
2792mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
2793{
2794 struct fw_event_work *fw_event;
2795
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302796 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2797 if (!fw_event)
2798 return;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05302799 fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302800 fw_event->ioc = ioc;
2801 _scsih_fw_event_add(ioc, fw_event);
2802}
2803
2804/**
2805 * _scsih_fw_event_cleanup_queue - cleanup event queue
2806 * @ioc: per adapter object
2807 *
2808 * Walk the firmware event queue, either killing timers, or waiting
2809 * for outstanding events to complete
2810 *
2811 * Return nothing.
2812 */
2813static void
2814_scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
2815{
2816 struct fw_event_work *fw_event, *next;
2817
2818 if (list_empty(&ioc->fw_event_list) ||
2819 !ioc->firmware_event_thread || in_interrupt())
Eric Moore635374e2009-03-09 01:21:12 -06002820 return;
2821
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05302822 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
2823 if (cancel_delayed_work(&fw_event->delayed_work)) {
2824 _scsih_fw_event_free(ioc, fw_event);
2825 continue;
2826 }
2827 fw_event->cancel_pending_work = 1;
2828 }
Eric Moore635374e2009-03-09 01:21:12 -06002829}
2830
Eric Moore635374e2009-03-09 01:21:12 -06002831/**
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302832 * _scsih_ublock_io_all_device - unblock every device
2833 * @ioc: per adapter object
2834 *
2835 * change the device state from block to running
2836 */
2837static void
2838_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2839{
2840 struct MPT2SAS_DEVICE *sas_device_priv_data;
2841 struct scsi_device *sdev;
2842
2843 shost_for_each_device(sdev, ioc->shost) {
2844 sas_device_priv_data = sdev->hostdata;
2845 if (!sas_device_priv_data)
2846 continue;
2847 if (!sas_device_priv_data->block)
2848 continue;
2849 sas_device_priv_data->block = 0;
2850 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
2851 "handle(0x%04x)\n",
2852 sas_device_priv_data->sas_target->handle));
2853 scsi_internal_device_unblock(sdev);
2854 }
2855}
2856/**
Eric Moore635374e2009-03-09 01:21:12 -06002857 * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
2858 * @ioc: per adapter object
2859 * @handle: device handle
2860 *
2861 * During device pull we need to appropiately set the sdev state.
2862 */
2863static void
2864_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2865{
2866 struct MPT2SAS_DEVICE *sas_device_priv_data;
2867 struct scsi_device *sdev;
2868
2869 shost_for_each_device(sdev, ioc->shost) {
2870 sas_device_priv_data = sdev->hostdata;
2871 if (!sas_device_priv_data)
2872 continue;
2873 if (!sas_device_priv_data->block)
2874 continue;
2875 if (sas_device_priv_data->sas_target->handle == handle) {
2876 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2877 MPT2SAS_INFO_FMT "SDEV_RUNNING: "
2878 "handle(0x%04x)\n", ioc->name, handle));
2879 sas_device_priv_data->block = 0;
Kashyap, Desai34a03be2009-08-20 13:23:19 +05302880 scsi_internal_device_unblock(sdev);
Eric Moore635374e2009-03-09 01:21:12 -06002881 }
2882 }
2883}
2884
2885/**
Kashyap, Desaif93213d2011-06-14 10:56:43 +05302886 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2887 * @ioc: per adapter object
2888 * @handle: device handle
2889 *
2890 * During device pull we need to appropiately set the sdev state.
2891 */
2892static void
2893_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2894{
2895 struct MPT2SAS_DEVICE *sas_device_priv_data;
2896 struct scsi_device *sdev;
2897
2898 shost_for_each_device(sdev, ioc->shost) {
2899 sas_device_priv_data = sdev->hostdata;
2900 if (!sas_device_priv_data)
2901 continue;
2902 if (sas_device_priv_data->block)
2903 continue;
2904 sas_device_priv_data->block = 1;
2905 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
2906 "handle(0x%04x)\n",
2907 sas_device_priv_data->sas_target->handle));
2908 scsi_internal_device_block(sdev);
2909 }
2910}
2911
2912
2913/**
Eric Moore635374e2009-03-09 01:21:12 -06002914 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2915 * @ioc: per adapter object
2916 * @handle: device handle
2917 *
2918 * During device pull we need to appropiately set the sdev state.
2919 */
2920static void
2921_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2922{
2923 struct MPT2SAS_DEVICE *sas_device_priv_data;
2924 struct scsi_device *sdev;
2925
2926 shost_for_each_device(sdev, ioc->shost) {
2927 sas_device_priv_data = sdev->hostdata;
2928 if (!sas_device_priv_data)
2929 continue;
2930 if (sas_device_priv_data->block)
2931 continue;
2932 if (sas_device_priv_data->sas_target->handle == handle) {
2933 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2934 MPT2SAS_INFO_FMT "SDEV_BLOCK: "
2935 "handle(0x%04x)\n", ioc->name, handle));
2936 sas_device_priv_data->block = 1;
Kashyap, Desai34a03be2009-08-20 13:23:19 +05302937 scsi_internal_device_block(sdev);
Eric Moore635374e2009-03-09 01:21:12 -06002938 }
2939 }
2940}
2941
2942/**
2943 * _scsih_block_io_to_children_attached_to_ex
2944 * @ioc: per adapter object
2945 * @sas_expander: the sas_device object
2946 *
2947 * This routine set sdev state to SDEV_BLOCK for all devices
2948 * attached to this expander. This function called when expander is
2949 * pulled.
2950 */
2951static void
2952_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
2953 struct _sas_node *sas_expander)
2954{
2955 struct _sas_port *mpt2sas_port;
2956 struct _sas_device *sas_device;
2957 struct _sas_node *expander_sibling;
2958 unsigned long flags;
2959
2960 if (!sas_expander)
2961 return;
2962
2963 list_for_each_entry(mpt2sas_port,
2964 &sas_expander->sas_port_list, port_list) {
2965 if (mpt2sas_port->remote_identify.device_type ==
2966 SAS_END_DEVICE) {
2967 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2968 sas_device =
2969 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
2970 mpt2sas_port->remote_identify.sas_address);
2971 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2972 if (!sas_device)
2973 continue;
2974 _scsih_block_io_device(ioc, sas_device->handle);
2975 }
2976 }
2977
2978 list_for_each_entry(mpt2sas_port,
2979 &sas_expander->sas_port_list, port_list) {
2980
2981 if (mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05302982 SAS_EDGE_EXPANDER_DEVICE ||
Eric Moore635374e2009-03-09 01:21:12 -06002983 mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05302984 SAS_FANOUT_EXPANDER_DEVICE) {
Eric Moore635374e2009-03-09 01:21:12 -06002985
2986 spin_lock_irqsave(&ioc->sas_node_lock, flags);
2987 expander_sibling =
2988 mpt2sas_scsih_expander_find_by_sas_address(
2989 ioc, mpt2sas_port->remote_identify.sas_address);
2990 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
2991 _scsih_block_io_to_children_attached_to_ex(ioc,
2992 expander_sibling);
2993 }
2994 }
2995}
2996
2997/**
2998 * _scsih_block_io_to_children_attached_directly
2999 * @ioc: per adapter object
3000 * @event_data: topology change event data
3001 *
3002 * This routine set sdev state to SDEV_BLOCK for all devices
3003 * direct attached during device pull.
3004 */
3005static void
3006_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
3007 Mpi2EventDataSasTopologyChangeList_t *event_data)
3008{
3009 int i;
3010 u16 handle;
3011 u16 reason_code;
3012 u8 phy_number;
3013
3014 for (i = 0; i < event_data->NumEntries; i++) {
3015 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3016 if (!handle)
3017 continue;
3018 phy_number = event_data->StartPhyNum + i;
3019 reason_code = event_data->PHY[i].PhyStatus &
3020 MPI2_EVENT_SAS_TOPO_RC_MASK;
3021 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
3022 _scsih_block_io_device(ioc, handle);
3023 }
3024}
3025
3026/**
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303027 * _scsih_tm_tr_send - send task management request
3028 * @ioc: per adapter object
3029 * @handle: device handle
3030 * Context: interrupt time.
3031 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003032 * This code is to initiate the device removal handshake protocol
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303033 * with controller firmware. This function will issue target reset
3034 * using high priority request queue. It will send a sas iounit
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003035 * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303036 *
3037 * This is designed to send muliple task management request at the same
3038 * time to the fifo. If the fifo is full, we will append the request,
3039 * and process it in a future completion.
3040 */
3041static void
3042_scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3043{
3044 Mpi2SCSITaskManagementRequest_t *mpi_request;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303045 u16 smid;
3046 struct _sas_device *sas_device;
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303047 struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
3048 u64 sas_address = 0;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303049 unsigned long flags;
3050 struct _tr_list *delayed_tr;
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303051 u32 ioc_state;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303052
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303053 if (ioc->remove_host) {
3054 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
3055 "removed: handle(0x%04x)\n", __func__, ioc->name, handle));
3056 return;
3057 } else if (ioc->pci_error_recovery) {
3058 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
3059 "error recovery: handle(0x%04x)\n", __func__, ioc->name,
3060 handle));
3061 return;
3062 }
3063 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
3064 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3065 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
3066 "operational: handle(0x%04x)\n", __func__, ioc->name,
3067 handle));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303068 return;
3069 }
3070
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303071 /* if PD, then return */
3072 if (test_bit(handle, ioc->pd_handles))
3073 return;
3074
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303075 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3076 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303077 if (sas_device && sas_device->starget &&
3078 sas_device->starget->hostdata) {
3079 sas_target_priv_data = sas_device->starget->hostdata;
3080 sas_target_priv_data->deleted = 1;
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303081 sas_address = sas_device->sas_address;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303082 }
3083 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303084
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303085 if (sas_target_priv_data) {
3086 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
3087 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
3088 (unsigned long long)sas_address));
3089 _scsih_ublock_io_device(ioc, handle);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05303090 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
nagalakshmi.nandigama@lsi.comf3db0322011-10-19 15:37:14 +05303091 }
3092
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303093 smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
3094 if (!smid) {
3095 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3096 if (!delayed_tr)
3097 return;
3098 INIT_LIST_HEAD(&delayed_tr->list);
3099 delayed_tr->handle = handle;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303100 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3101 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3102 "DELAYED:tr:handle(0x%04x), (open)\n",
3103 ioc->name, handle));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303104 return;
3105 }
3106
Kashyap, Desai1278b112010-03-09 17:34:13 +05303107 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
3108 "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
3109 ioc->tm_tr_cb_idx));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303110 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3111 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3112 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3113 mpi_request->DevHandle = cpu_to_le16(handle);
3114 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303115 mpt2sas_base_put_smid_hi_priority(ioc, smid);
3116}
3117
3118
3119
3120/**
3121 * _scsih_sas_control_complete - completion routine
3122 * @ioc: per adapter object
3123 * @smid: system request message index
3124 * @msix_index: MSIX table index supplied by the OS
3125 * @reply: reply message frame(lower 32bit addr)
3126 * Context: interrupt time.
3127 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003128 * This is the sas iounit control completion routine.
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303129 * This code is part of the code to initiate the device removal
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003130 * handshake protocol with controller firmware.
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303131 *
3132 * Return 1 meaning mf should be freed from _base_interrupt
3133 * 0 means the mf is freed from this function.
3134 */
3135static u8
3136_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
3137 u8 msix_index, u32 reply)
3138{
Kashyap, Desai363fa50f2010-11-13 04:29:20 +05303139#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303140 Mpi2SasIoUnitControlReply_t *mpi_reply =
3141 mpt2sas_base_get_reply_virt_addr(ioc, reply);
Kashyap, Desai363fa50f2010-11-13 04:29:20 +05303142#endif
Kashyap, Desai1278b112010-03-09 17:34:13 +05303143 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3144 "sc_complete:handle(0x%04x), (open) "
3145 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
3146 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
3147 le16_to_cpu(mpi_reply->IOCStatus),
3148 le32_to_cpu(mpi_reply->IOCLogInfo)));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303149 return 1;
3150}
3151
3152/**
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303153 * _scsih_tm_tr_volume_send - send target reset request for volumes
3154 * @ioc: per adapter object
3155 * @handle: device handle
3156 * Context: interrupt time.
3157 *
3158 * This is designed to send muliple task management request at the same
3159 * time to the fifo. If the fifo is full, we will append the request,
3160 * and process it in a future completion.
3161 */
3162static void
3163_scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3164{
3165 Mpi2SCSITaskManagementRequest_t *mpi_request;
3166 u16 smid;
3167 struct _tr_list *delayed_tr;
3168
Eric Moore3cb54692010-07-08 14:44:34 -06003169 if (ioc->shost_recovery || ioc->remove_host ||
3170 ioc->pci_error_recovery) {
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303171 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
3172 "progress!\n", __func__, ioc->name));
3173 return;
3174 }
3175
3176 smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3177 if (!smid) {
3178 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3179 if (!delayed_tr)
3180 return;
3181 INIT_LIST_HEAD(&delayed_tr->list);
3182 delayed_tr->handle = handle;
3183 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3184 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3185 "DELAYED:tr:handle(0x%04x), (open)\n",
3186 ioc->name, handle));
3187 return;
3188 }
3189
3190 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
3191 "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
3192 ioc->tm_tr_volume_cb_idx));
3193 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3194 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3195 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3196 mpi_request->DevHandle = cpu_to_le16(handle);
3197 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3198 mpt2sas_base_put_smid_hi_priority(ioc, smid);
3199}
3200
3201/**
3202 * _scsih_tm_volume_tr_complete - target reset completion
3203 * @ioc: per adapter object
3204 * @smid: system request message index
3205 * @msix_index: MSIX table index supplied by the OS
3206 * @reply: reply message frame(lower 32bit addr)
3207 * Context: interrupt time.
3208 *
3209 * Return 1 meaning mf should be freed from _base_interrupt
3210 * 0 means the mf is freed from this function.
3211 */
3212static u8
3213_scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
3214 u8 msix_index, u32 reply)
3215{
3216 u16 handle;
3217 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3218 Mpi2SCSITaskManagementReply_t *mpi_reply =
3219 mpt2sas_base_get_reply_virt_addr(ioc, reply);
3220
Eric Moore3cb54692010-07-08 14:44:34 -06003221 if (ioc->shost_recovery || ioc->remove_host ||
3222 ioc->pci_error_recovery) {
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303223 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
3224 "progress!\n", __func__, ioc->name));
3225 return 1;
3226 }
3227
3228 mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
3229 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3230 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3231 dewtprintk(ioc, printk("spurious interrupt: "
3232 "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle,
3233 le16_to_cpu(mpi_reply->DevHandle), smid));
3234 return 0;
3235 }
3236
3237 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3238 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3239 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3240 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3241 le32_to_cpu(mpi_reply->IOCLogInfo),
3242 le32_to_cpu(mpi_reply->TerminationCount)));
3243
3244 return _scsih_check_for_pending_tm(ioc, smid);
3245}
3246
3247/**
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303248 * _scsih_tm_tr_complete -
3249 * @ioc: per adapter object
3250 * @smid: system request message index
3251 * @msix_index: MSIX table index supplied by the OS
3252 * @reply: reply message frame(lower 32bit addr)
3253 * Context: interrupt time.
3254 *
3255 * This is the target reset completion routine.
3256 * This code is part of the code to initiate the device removal
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003257 * handshake protocol with controller firmware.
3258 * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303259 *
3260 * Return 1 meaning mf should be freed from _base_interrupt
3261 * 0 means the mf is freed from this function.
3262 */
3263static u8
3264_scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
3265 u32 reply)
3266{
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303267 u16 handle;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303268 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303269 Mpi2SCSITaskManagementReply_t *mpi_reply =
3270 mpt2sas_base_get_reply_virt_addr(ioc, reply);
3271 Mpi2SasIoUnitControlRequest_t *mpi_request;
3272 u16 smid_sas_ctrl;
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303273 u32 ioc_state;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303274
nagalakshmi.nandigama@lsi.comf881cea2011-10-19 15:37:00 +05303275 if (ioc->remove_host) {
3276 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
3277 "removed\n", __func__, ioc->name));
3278 return 1;
3279 } else if (ioc->pci_error_recovery) {
3280 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
3281 "error recovery\n", __func__, ioc->name));
3282 return 1;
3283 }
3284 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
3285 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3286 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
3287 "operational\n", __func__, ioc->name));
Kashyap, Desai1278b112010-03-09 17:34:13 +05303288 return 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303289 }
3290
Kashyap, Desai1278b112010-03-09 17:34:13 +05303291 mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
3292 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3293 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3294 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "spurious interrupt: "
3295 "handle(0x%04x:0x%04x), smid(%d)!!!\n", ioc->name, handle,
3296 le16_to_cpu(mpi_reply->DevHandle), smid));
3297 return 0;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303298 }
3299
Kashyap, Desai1278b112010-03-09 17:34:13 +05303300 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3301 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3302 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3303 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3304 le32_to_cpu(mpi_reply->IOCLogInfo),
3305 le32_to_cpu(mpi_reply->TerminationCount)));
3306
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303307 smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
3308 if (!smid_sas_ctrl) {
3309 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3310 ioc->name, __func__);
Kashyap, Desai1278b112010-03-09 17:34:13 +05303311 return 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303312 }
3313
Kashyap, Desai1278b112010-03-09 17:34:13 +05303314 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sc_send:handle(0x%04x), "
3315 "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid_sas_ctrl,
3316 ioc->tm_sas_control_cb_idx));
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303317 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl);
3318 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3319 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3320 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303321 mpi_request->DevHandle = mpi_request_tm->DevHandle;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303322 mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl);
Kashyap, Desai1278b112010-03-09 17:34:13 +05303323
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303324 return _scsih_check_for_pending_tm(ioc, smid);
3325}
3326
3327/**
3328 * _scsih_check_for_pending_tm - check for pending task management
3329 * @ioc: per adapter object
3330 * @smid: system request message index
3331 *
3332 * This will check delayed target reset list, and feed the
3333 * next reqeust.
3334 *
3335 * Return 1 meaning mf should be freed from _base_interrupt
3336 * 0 means the mf is freed from this function.
3337 */
3338static u8
3339_scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid)
3340{
3341 struct _tr_list *delayed_tr;
3342
3343 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3344 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3345 struct _tr_list, list);
3346 mpt2sas_base_free_smid(ioc, smid);
3347 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3348 list_del(&delayed_tr->list);
3349 kfree(delayed_tr);
3350 return 0;
3351 }
3352
Kashyap, Desai1278b112010-03-09 17:34:13 +05303353 if (!list_empty(&ioc->delayed_tr_list)) {
3354 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3355 struct _tr_list, list);
3356 mpt2sas_base_free_smid(ioc, smid);
3357 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3358 list_del(&delayed_tr->list);
3359 kfree(delayed_tr);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303360 return 0;
Kashyap, Desai1278b112010-03-09 17:34:13 +05303361 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303362
Kashyap, Desai1278b112010-03-09 17:34:13 +05303363 return 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303364}
3365
3366/**
Eric Moore635374e2009-03-09 01:21:12 -06003367 * _scsih_check_topo_delete_events - sanity check on topo events
3368 * @ioc: per adapter object
3369 * @event_data: the event data payload
3370 *
3371 * This routine added to better handle cable breaker.
3372 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003373 * This handles the case where driver receives multiple expander
Eric Moore635374e2009-03-09 01:21:12 -06003374 * add and delete events in a single shot. When there is a delete event
3375 * the routine will void any pending add events waiting in the event queue.
3376 *
3377 * Return nothing.
3378 */
3379static void
3380_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
3381 Mpi2EventDataSasTopologyChangeList_t *event_data)
3382{
3383 struct fw_event_work *fw_event;
3384 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3385 u16 expander_handle;
3386 struct _sas_node *sas_expander;
3387 unsigned long flags;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303388 int i, reason_code;
3389 u16 handle;
3390
3391 for (i = 0 ; i < event_data->NumEntries; i++) {
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303392 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3393 if (!handle)
3394 continue;
3395 reason_code = event_data->PHY[i].PhyStatus &
3396 MPI2_EVENT_SAS_TOPO_RC_MASK;
3397 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3398 _scsih_tm_tr_send(ioc, handle);
3399 }
Eric Moore635374e2009-03-09 01:21:12 -06003400
3401 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3402 if (expander_handle < ioc->sas_hba.num_phys) {
3403 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3404 return;
3405 }
3406
3407 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING
3408 || event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) {
3409 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3410 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
3411 expander_handle);
3412 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3413 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
3414 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3415 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3416
3417 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3418 return;
3419
3420 /* mark ignore flag for pending events */
3421 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3422 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3423 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3424 fw_event->ignore)
3425 continue;
3426 local_event_data = fw_event->event_data;
3427 if (local_event_data->ExpStatus ==
3428 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3429 local_event_data->ExpStatus ==
3430 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3431 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3432 expander_handle) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303433 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06003434 "setting ignoring flag\n", ioc->name));
3435 fw_event->ignore = 1;
3436 }
3437 }
3438 }
3439 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3440}
3441
3442/**
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303443 * _scsih_set_volume_delete_flag - setting volume delete flag
3444 * @ioc: per adapter object
3445 * @handle: device handle
3446 *
3447 * This
3448 * Return nothing.
3449 */
3450static void
3451_scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3452{
3453 struct _raid_device *raid_device;
3454 struct MPT2SAS_TARGET *sas_target_priv_data;
3455 unsigned long flags;
3456
3457 spin_lock_irqsave(&ioc->raid_device_lock, flags);
3458 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
3459 if (raid_device && raid_device->starget &&
3460 raid_device->starget->hostdata) {
3461 sas_target_priv_data =
3462 raid_device->starget->hostdata;
3463 sas_target_priv_data->deleted = 1;
3464 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3465 "setting delete flag: handle(0x%04x), "
3466 "wwid(0x%016llx)\n", ioc->name, handle,
3467 (unsigned long long) raid_device->wwid));
3468 }
3469 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3470}
3471
3472/**
3473 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3474 * @handle: input handle
3475 * @a: handle for volume a
3476 * @b: handle for volume b
3477 *
3478 * IR firmware only supports two raid volumes. The purpose of this
3479 * routine is to set the volume handle in either a or b. When the given
3480 * input handle is non-zero, or when a and b have not been set before.
3481 */
3482static void
3483_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3484{
3485 if (!handle || handle == *a || handle == *b)
3486 return;
3487 if (!*a)
3488 *a = handle;
3489 else if (!*b)
3490 *b = handle;
3491}
3492
3493/**
3494 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3495 * @ioc: per adapter object
3496 * @event_data: the event data payload
3497 * Context: interrupt time.
3498 *
3499 * This routine will send target reset to volume, followed by target
3500 * resets to the PDs. This is called when a PD has been removed, or
3501 * volume has been deleted or removed. When the target reset is sent
3502 * to volume, the PD target resets need to be queued to start upon
3503 * completion of the volume target reset.
3504 *
3505 * Return nothing.
3506 */
3507static void
3508_scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc,
3509 Mpi2EventDataIrConfigChangeList_t *event_data)
3510{
3511 Mpi2EventIrConfigElement_t *element;
3512 int i;
3513 u16 handle, volume_handle, a, b;
3514 struct _tr_list *delayed_tr;
3515
3516 a = 0;
3517 b = 0;
3518
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303519 if (ioc->is_warpdrive)
3520 return;
3521
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303522 /* Volume Resets for Deleted or Removed */
3523 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3524 for (i = 0; i < event_data->NumElements; i++, element++) {
3525 if (element->ReasonCode ==
3526 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3527 element->ReasonCode ==
3528 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3529 volume_handle = le16_to_cpu(element->VolDevHandle);
3530 _scsih_set_volume_delete_flag(ioc, volume_handle);
3531 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3532 }
3533 }
3534
3535 /* Volume Resets for UNHIDE events */
3536 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3537 for (i = 0; i < event_data->NumElements; i++, element++) {
3538 if (le32_to_cpu(event_data->Flags) &
3539 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3540 continue;
3541 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3542 volume_handle = le16_to_cpu(element->VolDevHandle);
3543 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3544 }
3545 }
3546
3547 if (a)
3548 _scsih_tm_tr_volume_send(ioc, a);
3549 if (b)
3550 _scsih_tm_tr_volume_send(ioc, b);
3551
3552 /* PD target resets */
3553 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3554 for (i = 0; i < event_data->NumElements; i++, element++) {
3555 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3556 continue;
3557 handle = le16_to_cpu(element->PhysDiskDevHandle);
3558 volume_handle = le16_to_cpu(element->VolDevHandle);
3559 clear_bit(handle, ioc->pd_handles);
3560 if (!volume_handle)
3561 _scsih_tm_tr_send(ioc, handle);
3562 else if (volume_handle == a || volume_handle == b) {
3563 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3564 BUG_ON(!delayed_tr);
3565 INIT_LIST_HEAD(&delayed_tr->list);
3566 delayed_tr->handle = handle;
3567 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3568 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
3569 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3570 handle));
3571 } else
3572 _scsih_tm_tr_send(ioc, handle);
3573 }
3574}
3575
3576
3577/**
3578 * _scsih_check_volume_delete_events - set delete flag for volumes
3579 * @ioc: per adapter object
3580 * @event_data: the event data payload
3581 * Context: interrupt time.
3582 *
3583 * This will handle the case when the cable connected to entire volume is
3584 * pulled. We will take care of setting the deleted flag so normal IO will
3585 * not be sent.
3586 *
3587 * Return nothing.
3588 */
3589static void
3590_scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc,
3591 Mpi2EventDataIrVolume_t *event_data)
3592{
3593 u32 state;
3594
3595 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3596 return;
3597 state = le32_to_cpu(event_data->NewValue);
3598 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3599 MPI2_RAID_VOL_STATE_FAILED)
3600 _scsih_set_volume_delete_flag(ioc,
3601 le16_to_cpu(event_data->VolDevHandle));
3602}
3603
3604/**
Eric Moore635374e2009-03-09 01:21:12 -06003605 * _scsih_flush_running_cmds - completing outstanding commands.
3606 * @ioc: per adapter object
3607 *
3608 * The flushing out of all pending scmd commands following host reset,
3609 * where all IO is dropped to the floor.
3610 *
3611 * Return nothing.
3612 */
3613static void
3614_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
3615{
3616 struct scsi_cmnd *scmd;
3617 u16 smid;
3618 u16 count = 0;
3619
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303620 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
Kashyap, Desaiec07a052011-01-05 17:54:32 +05303621 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06003622 if (!scmd)
3623 continue;
3624 count++;
3625 mpt2sas_base_free_smid(ioc, smid);
3626 scsi_dma_unmap(scmd);
Eric Moore3cb54692010-07-08 14:44:34 -06003627 if (ioc->pci_error_recovery)
3628 scmd->result = DID_NO_CONNECT << 16;
3629 else
3630 scmd->result = DID_RESET << 16;
Eric Moore635374e2009-03-09 01:21:12 -06003631 scmd->scsi_done(scmd);
3632 }
3633 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n",
3634 ioc->name, count));
3635}
3636
3637/**
Eric Moore3c621b32009-05-18 12:59:41 -06003638 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3639 * @scmd: pointer to scsi command object
3640 * @mpi_request: pointer to the SCSI_IO reqest message frame
3641 *
3642 * Supporting protection 1 and 3.
3643 *
3644 * Returns nothing
3645 */
3646static void
3647_scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request)
3648{
3649 u16 eedp_flags;
3650 unsigned char prot_op = scsi_get_prot_op(scmd);
3651 unsigned char prot_type = scsi_get_prot_type(scmd);
3652
Eric Moored334aa72010-04-22 10:47:40 -06003653 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
Eric Moore3c621b32009-05-18 12:59:41 -06003654 return;
3655
3656 if (prot_op == SCSI_PROT_READ_STRIP)
3657 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3658 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3659 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3660 else
3661 return;
3662
Eric Moore3c621b32009-05-18 12:59:41 -06003663 switch (prot_type) {
3664 case SCSI_PROT_DIF_TYPE1:
Martin K. Petersen756aca72011-05-18 00:45:22 -04003665 case SCSI_PROT_DIF_TYPE2:
Eric Moore3c621b32009-05-18 12:59:41 -06003666
3667 /*
3668 * enable ref/guard checking
3669 * auto increment ref tag
3670 */
Kashyap, Desai463217b2009-10-05 15:53:06 +05303671 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
Eric Moore3c621b32009-05-18 12:59:41 -06003672 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
3673 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3674 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
3675 cpu_to_be32(scsi_get_lba(scmd));
Eric Moored334aa72010-04-22 10:47:40 -06003676 break;
Eric Moore3c621b32009-05-18 12:59:41 -06003677
Eric Moore3c621b32009-05-18 12:59:41 -06003678 case SCSI_PROT_DIF_TYPE3:
3679
3680 /*
3681 * enable guard checking
3682 */
Kashyap, Desai463217b2009-10-05 15:53:06 +05303683 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
Eric Moore3c621b32009-05-18 12:59:41 -06003684 break;
3685 }
Kashyap, Desai463217b2009-10-05 15:53:06 +05303686 mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size);
3687 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
Eric Moore3c621b32009-05-18 12:59:41 -06003688}
3689
3690/**
3691 * _scsih_eedp_error_handling - return sense code for EEDP errors
3692 * @scmd: pointer to scsi command object
3693 * @ioc_status: ioc status
3694 *
3695 * Returns nothing
3696 */
3697static void
3698_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
3699{
3700 u8 ascq;
3701 u8 sk;
3702 u8 host_byte;
3703
3704 switch (ioc_status) {
3705 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
3706 ascq = 0x01;
3707 break;
3708 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
3709 ascq = 0x02;
3710 break;
3711 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
3712 ascq = 0x03;
3713 break;
3714 default:
3715 ascq = 0x00;
3716 break;
3717 }
3718
3719 if (scmd->sc_data_direction == DMA_TO_DEVICE) {
3720 sk = ILLEGAL_REQUEST;
3721 host_byte = DID_ABORT;
3722 } else {
3723 sk = ABORTED_COMMAND;
3724 host_byte = DID_OK;
3725 }
3726
3727 scsi_build_sense_buffer(0, scmd->sense_buffer, sk, 0x10, ascq);
3728 scmd->result = DRIVER_SENSE << 24 | (host_byte << 16) |
3729 SAM_STAT_CHECK_CONDITION;
3730}
3731
3732/**
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303733 * _scsih_scsi_direct_io_get - returns direct io flag
3734 * @ioc: per adapter object
3735 * @smid: system request message index
3736 *
3737 * Returns the smid stored scmd pointer.
3738 */
3739static inline u8
3740_scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
3741{
3742 return ioc->scsi_lookup[smid - 1].direct_io;
3743}
3744
3745/**
3746 * _scsih_scsi_direct_io_set - sets direct io flag
3747 * @ioc: per adapter object
3748 * @smid: system request message index
3749 * @direct_io: Zero or non-zero value to set in the direct_io flag
3750 *
3751 * Returns Nothing.
3752 */
3753static inline void
3754_scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
3755{
3756 ioc->scsi_lookup[smid - 1].direct_io = direct_io;
3757}
3758
3759
3760/**
3761 * _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
3762 * @ioc: per adapter object
3763 * @scmd: pointer to scsi command object
3764 * @raid_device: pointer to raid device data structure
3765 * @mpi_request: pointer to the SCSI_IO reqest message frame
3766 * @smid: system request message index
3767 *
3768 * Returns nothing
3769 */
3770static void
3771_scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3772 struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
3773 u16 smid)
3774{
3775 u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size;
3776 u32 stripe_sz, stripe_exp;
3777 u8 num_pds, *cdb_ptr, *tmp_ptr, *lba_ptr1, *lba_ptr2;
3778 u8 cdb0 = scmd->cmnd[0];
3779
3780 /*
3781 * Try Direct I/O to RAID memeber disks
3782 */
3783 if (cdb0 == READ_16 || cdb0 == READ_10 ||
3784 cdb0 == WRITE_16 || cdb0 == WRITE_10) {
3785 cdb_ptr = mpi_request->CDB.CDB32;
3786
3787 if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4]
3788 | cdb_ptr[5])) {
3789 io_size = scsi_bufflen(scmd) >> 9;
3790 /* get virtual lba */
3791 lba_ptr1 = lba_ptr2 = (cdb0 < READ_16) ? &cdb_ptr[2] :
3792 &cdb_ptr[6];
3793 tmp_ptr = (u8 *)&v_lba + 3;
3794 *tmp_ptr-- = *lba_ptr1++;
3795 *tmp_ptr-- = *lba_ptr1++;
3796 *tmp_ptr-- = *lba_ptr1++;
3797 *tmp_ptr = *lba_ptr1;
3798
3799 if (((u64)v_lba + (u64)io_size - 1) <=
3800 (u32)raid_device->max_lba) {
3801 stripe_sz = raid_device->stripe_sz;
3802 stripe_exp = raid_device->stripe_exponent;
3803 stripe_off = v_lba & (stripe_sz - 1);
3804
3805 /* Check whether IO falls within a stripe */
3806 if ((stripe_off + io_size) <= stripe_sz) {
3807 num_pds = raid_device->num_pds;
3808 p_lba = v_lba >> stripe_exp;
3809 stripe_unit = p_lba / num_pds;
3810 column = p_lba % num_pds;
3811 p_lba = (stripe_unit << stripe_exp) +
3812 stripe_off;
3813 mpi_request->DevHandle =
3814 cpu_to_le16(raid_device->
3815 pd_handle[column]);
3816 tmp_ptr = (u8 *)&p_lba + 3;
3817 *lba_ptr2++ = *tmp_ptr--;
3818 *lba_ptr2++ = *tmp_ptr--;
3819 *lba_ptr2++ = *tmp_ptr--;
3820 *lba_ptr2 = *tmp_ptr;
3821 /*
3822 * WD: To indicate this I/O is directI/O
3823 */
3824 _scsih_scsi_direct_io_set(ioc, smid, 1);
3825 }
3826 }
3827 }
3828 }
3829}
3830
3831/**
Eric Moored5d135b2009-05-18 13:02:08 -06003832 * _scsih_qcmd - main scsi request entry point
Eric Moore635374e2009-03-09 01:21:12 -06003833 * @scmd: pointer to scsi command object
3834 * @done: function pointer to be invoked on completion
3835 *
3836 * The callback index is set inside `ioc->scsi_io_cb_idx`.
3837 *
3838 * Returns 0 on success. If there's a failure, return either:
3839 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
3840 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
3841 */
3842static int
Jeff Garzikf2812332010-11-16 02:10:29 -05003843_scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
Eric Moore635374e2009-03-09 01:21:12 -06003844{
3845 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
3846 struct MPT2SAS_DEVICE *sas_device_priv_data;
3847 struct MPT2SAS_TARGET *sas_target_priv_data;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303848 struct _raid_device *raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06003849 Mpi2SCSIIORequest_t *mpi_request;
3850 u32 mpi_control;
3851 u16 smid;
Eric Moore635374e2009-03-09 01:21:12 -06003852
3853 scmd->scsi_done = done;
3854 sas_device_priv_data = scmd->device->hostdata;
Kashyap, Desai130b9582010-04-08 17:54:32 +05303855 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
Eric Moore635374e2009-03-09 01:21:12 -06003856 scmd->result = DID_NO_CONNECT << 16;
3857 scmd->scsi_done(scmd);
3858 return 0;
3859 }
3860
Kashyap, Desai78215782011-06-14 10:57:08 +05303861 if (ioc->pci_error_recovery || ioc->remove_host) {
Eric Moore3cb54692010-07-08 14:44:34 -06003862 scmd->result = DID_NO_CONNECT << 16;
3863 scmd->scsi_done(scmd);
3864 return 0;
3865 }
3866
Eric Moore635374e2009-03-09 01:21:12 -06003867 sas_target_priv_data = sas_device_priv_data->sas_target;
Kashyap, Desai130b9582010-04-08 17:54:32 +05303868 /* invalid device handle */
3869 if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
Eric Moore635374e2009-03-09 01:21:12 -06003870 scmd->result = DID_NO_CONNECT << 16;
3871 scmd->scsi_done(scmd);
3872 return 0;
3873 }
3874
Kashyap, Desai130b9582010-04-08 17:54:32 +05303875 /* host recovery or link resets sent via IOCTLs */
3876 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
Eric Moore635374e2009-03-09 01:21:12 -06003877 return SCSI_MLQUEUE_HOST_BUSY;
Uwe Kleine-König65155b32010-06-11 12:17:01 +02003878 /* device busy with task management */
Kashyap, Desai130b9582010-04-08 17:54:32 +05303879 else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
3880 return SCSI_MLQUEUE_DEVICE_BUSY;
3881 /* device has been deleted */
3882 else if (sas_target_priv_data->deleted) {
3883 scmd->result = DID_NO_CONNECT << 16;
3884 scmd->scsi_done(scmd);
3885 return 0;
3886 }
Eric Moore635374e2009-03-09 01:21:12 -06003887
3888 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
3889 mpi_control = MPI2_SCSIIO_CONTROL_READ;
3890 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
3891 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
3892 else
3893 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
3894
3895 /* set tags */
3896 if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
3897 if (scmd->device->tagged_supported) {
3898 if (scmd->device->ordered_tags)
3899 mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
3900 else
3901 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
3902 } else
3903/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */
3904/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED;
3905 */
3906 mpi_control |= (0x500);
3907
3908 } else
3909 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303910 /* Make sure Device is not raid volume.
3911 * We do not expose raid functionality to upper layer for warpdrive.
3912 */
3913 if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
Eric Moored334aa72010-04-22 10:47:40 -06003914 sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
Eric Moore635374e2009-03-09 01:21:12 -06003915 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
3916
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303917 smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
Eric Moore635374e2009-03-09 01:21:12 -06003918 if (!smid) {
3919 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3920 ioc->name, __func__);
3921 goto out;
3922 }
3923 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3924 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
Eric Moore3c621b32009-05-18 12:59:41 -06003925 _scsih_setup_eedp(scmd, mpi_request);
Eric Moored334aa72010-04-22 10:47:40 -06003926 if (scmd->cmd_len == 32)
3927 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
Eric Moore635374e2009-03-09 01:21:12 -06003928 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3929 if (sas_device_priv_data->sas_target->flags &
3930 MPT_TARGET_FLAGS_RAID_COMPONENT)
3931 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3932 else
3933 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3934 mpi_request->DevHandle =
3935 cpu_to_le16(sas_device_priv_data->sas_target->handle);
3936 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
3937 mpi_request->Control = cpu_to_le32(mpi_control);
3938 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
3939 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
3940 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
3941 mpi_request->SenseBufferLowAddress =
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05303942 mpt2sas_base_get_sense_buffer_dma(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06003943 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
3944 mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI +
3945 MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303946 mpi_request->VF_ID = 0; /* TODO */
3947 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003948 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
3949 mpi_request->LUN);
3950 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
3951
3952 if (!mpi_request->DataLength) {
3953 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL);
3954 } else {
3955 if (_scsih_build_scatter_gather(ioc, scmd, smid)) {
3956 mpt2sas_base_free_smid(ioc, smid);
3957 goto out;
3958 }
3959 }
3960
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303961 raid_device = sas_target_priv_data->raid_device;
3962 if (raid_device && raid_device->direct_io_enabled)
3963 _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
3964 smid);
3965
Kashyap, Desai58287fd2010-03-17 16:27:25 +05303966 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST))
3967 mpt2sas_base_put_smid_scsi_io(ioc, smid,
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303968 le16_to_cpu(mpi_request->DevHandle));
Kashyap, Desai58287fd2010-03-17 16:27:25 +05303969 else
3970 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06003971 return 0;
3972
3973 out:
3974 return SCSI_MLQUEUE_HOST_BUSY;
3975}
3976
Jeff Garzikf2812332010-11-16 02:10:29 -05003977static DEF_SCSI_QCMD(_scsih_qcmd)
3978
Eric Moore635374e2009-03-09 01:21:12 -06003979/**
3980 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
3981 * @sense_buffer: sense data returned by target
3982 * @data: normalized skey/asc/ascq
3983 *
3984 * Return nothing.
3985 */
3986static void
3987_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
3988{
3989 if ((sense_buffer[0] & 0x7F) >= 0x72) {
3990 /* descriptor format */
3991 data->skey = sense_buffer[1] & 0x0F;
3992 data->asc = sense_buffer[2];
3993 data->ascq = sense_buffer[3];
3994 } else {
3995 /* fixed format */
3996 data->skey = sense_buffer[2] & 0x0F;
3997 data->asc = sense_buffer[12];
3998 data->ascq = sense_buffer[13];
3999 }
4000}
4001
4002#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4003/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -03004004 * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request
Eric Moore635374e2009-03-09 01:21:12 -06004005 * @ioc: per adapter object
4006 * @scmd: pointer to scsi command object
4007 * @mpi_reply: reply mf payload returned from firmware
4008 *
4009 * scsi_status - SCSI Status code returned from target device
4010 * scsi_state - state info associated with SCSI_IO determined by ioc
4011 * ioc_status - ioc supplied status info
4012 *
4013 * Return nothing.
4014 */
4015static void
4016_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
4017 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
4018{
4019 u32 response_info;
4020 u8 *response_bytes;
4021 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
4022 MPI2_IOCSTATUS_MASK;
4023 u8 scsi_state = mpi_reply->SCSIState;
4024 u8 scsi_status = mpi_reply->SCSIStatus;
4025 char *desc_ioc_state = NULL;
4026 char *desc_scsi_status = NULL;
4027 char *desc_scsi_state = ioc->tmp_string;
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +05304028 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304029 struct _sas_device *sas_device = NULL;
4030 unsigned long flags;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304031 struct scsi_target *starget = scmd->device->sdev_target;
4032 struct MPT2SAS_TARGET *priv_target = starget->hostdata;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304033 char *device_str = NULL;
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304034
4035 if (!priv_target)
4036 return;
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +05304037
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304038 if (ioc->hide_ir_msg)
4039 device_str = "WarpDrive";
4040 else
4041 device_str = "volume";
4042
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +05304043 if (log_info == 0x31170000)
4044 return;
Eric Moore635374e2009-03-09 01:21:12 -06004045
4046 switch (ioc_status) {
4047 case MPI2_IOCSTATUS_SUCCESS:
4048 desc_ioc_state = "success";
4049 break;
4050 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4051 desc_ioc_state = "invalid function";
4052 break;
4053 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4054 desc_ioc_state = "scsi recovered error";
4055 break;
4056 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
4057 desc_ioc_state = "scsi invalid dev handle";
4058 break;
4059 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4060 desc_ioc_state = "scsi device not there";
4061 break;
4062 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4063 desc_ioc_state = "scsi data overrun";
4064 break;
4065 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4066 desc_ioc_state = "scsi data underrun";
4067 break;
4068 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4069 desc_ioc_state = "scsi io data error";
4070 break;
4071 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4072 desc_ioc_state = "scsi protocol error";
4073 break;
4074 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4075 desc_ioc_state = "scsi task terminated";
4076 break;
4077 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4078 desc_ioc_state = "scsi residual mismatch";
4079 break;
4080 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4081 desc_ioc_state = "scsi task mgmt failed";
4082 break;
4083 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4084 desc_ioc_state = "scsi ioc terminated";
4085 break;
4086 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4087 desc_ioc_state = "scsi ext terminated";
4088 break;
Eric Moore3c621b32009-05-18 12:59:41 -06004089 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4090 desc_ioc_state = "eedp guard error";
4091 break;
4092 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4093 desc_ioc_state = "eedp ref tag error";
4094 break;
4095 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4096 desc_ioc_state = "eedp app tag error";
4097 break;
Eric Moore635374e2009-03-09 01:21:12 -06004098 default:
4099 desc_ioc_state = "unknown";
4100 break;
4101 }
4102
4103 switch (scsi_status) {
4104 case MPI2_SCSI_STATUS_GOOD:
4105 desc_scsi_status = "good";
4106 break;
4107 case MPI2_SCSI_STATUS_CHECK_CONDITION:
4108 desc_scsi_status = "check condition";
4109 break;
4110 case MPI2_SCSI_STATUS_CONDITION_MET:
4111 desc_scsi_status = "condition met";
4112 break;
4113 case MPI2_SCSI_STATUS_BUSY:
4114 desc_scsi_status = "busy";
4115 break;
4116 case MPI2_SCSI_STATUS_INTERMEDIATE:
4117 desc_scsi_status = "intermediate";
4118 break;
4119 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
4120 desc_scsi_status = "intermediate condmet";
4121 break;
4122 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
4123 desc_scsi_status = "reservation conflict";
4124 break;
4125 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
4126 desc_scsi_status = "command terminated";
4127 break;
4128 case MPI2_SCSI_STATUS_TASK_SET_FULL:
4129 desc_scsi_status = "task set full";
4130 break;
4131 case MPI2_SCSI_STATUS_ACA_ACTIVE:
4132 desc_scsi_status = "aca active";
4133 break;
4134 case MPI2_SCSI_STATUS_TASK_ABORTED:
4135 desc_scsi_status = "task aborted";
4136 break;
4137 default:
4138 desc_scsi_status = "unknown";
4139 break;
4140 }
4141
4142 desc_scsi_state[0] = '\0';
4143 if (!scsi_state)
4144 desc_scsi_state = " ";
4145 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4146 strcat(desc_scsi_state, "response info ");
4147 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4148 strcat(desc_scsi_state, "state terminated ");
4149 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
4150 strcat(desc_scsi_state, "no status ");
4151 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
4152 strcat(desc_scsi_state, "autosense failed ");
4153 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
4154 strcat(desc_scsi_state, "autosense valid ");
4155
4156 scsi_print_command(scmd);
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304157
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304158 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304159 printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
4160 device_str, (unsigned long long)priv_target->sas_address);
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304161 } else {
4162 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4163 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
4164 priv_target->sas_address);
4165 if (sas_device) {
4166 printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
4167 "phy(%d)\n", ioc->name, sas_device->sas_address,
4168 sas_device->phy);
4169 printk(MPT2SAS_WARN_FMT
4170 "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
4171 ioc->name, sas_device->enclosure_logical_id,
4172 sas_device->slot);
4173 }
4174 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304175 }
Kashyap, Desai7fbae672010-06-17 13:45:17 +05304176
Kashyap, Desai8e864a82010-06-17 13:48:46 +05304177 printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), "
4178 "smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle),
4179 desc_ioc_state, ioc_status, smid);
Eric Moore635374e2009-03-09 01:21:12 -06004180 printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), "
4181 "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow,
4182 scsi_get_resid(scmd));
4183 printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), "
4184 "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag),
4185 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
4186 printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), "
4187 "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status,
4188 scsi_status, desc_scsi_state, scsi_state);
4189
4190 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4191 struct sense_info data;
4192 _scsih_normalize_sense(scmd->sense_buffer, &data);
4193 printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: "
Kashyap, Desaie94f6742010-03-17 16:24:52 +05304194 "[0x%02x,0x%02x,0x%02x], count(%d)\n", ioc->name, data.skey,
4195 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
Eric Moore635374e2009-03-09 01:21:12 -06004196 }
4197
4198 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
4199 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
4200 response_bytes = (u8 *)&response_info;
Kashyap, Desai9982f592009-09-23 17:23:07 +05304201 _scsih_response_code(ioc, response_bytes[0]);
Eric Moore635374e2009-03-09 01:21:12 -06004202 }
4203}
4204#endif
4205
4206/**
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05304207 * _scsih_turn_on_fault_led - illuminate Fault LED
Eric Moore635374e2009-03-09 01:21:12 -06004208 * @ioc: per adapter object
4209 * @handle: device handle
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05304210 * Context: process
4211 *
4212 * Return nothing.
4213 */
4214static void
4215_scsih_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4216{
4217 Mpi2SepReply_t mpi_reply;
4218 Mpi2SepRequest_t mpi_request;
4219
4220 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4221 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4222 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4223 mpi_request.SlotStatus =
4224 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
4225 mpi_request.DevHandle = cpu_to_le16(handle);
4226 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
4227 if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4228 &mpi_request)) != 0) {
4229 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
4230 __FILE__, __LINE__, __func__);
4231 return;
4232 }
4233
4234 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4235 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: "
4236 "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name,
4237 le16_to_cpu(mpi_reply.IOCStatus),
4238 le32_to_cpu(mpi_reply.IOCLogInfo)));
4239 return;
4240 }
4241}
4242
4243/**
4244 * _scsih_send_event_to_turn_on_fault_led - fire delayed event
4245 * @ioc: per adapter object
4246 * @handle: device handle
4247 * Context: interrupt.
4248 *
4249 * Return nothing.
4250 */
4251static void
4252_scsih_send_event_to_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4253{
4254 struct fw_event_work *fw_event;
4255
4256 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
4257 if (!fw_event)
4258 return;
4259 fw_event->event = MPT2SAS_TURN_ON_FAULT_LED;
4260 fw_event->device_handle = handle;
4261 fw_event->ioc = ioc;
4262 _scsih_fw_event_add(ioc, fw_event);
4263}
4264
4265/**
4266 * _scsih_smart_predicted_fault - process smart errors
4267 * @ioc: per adapter object
4268 * @handle: device handle
4269 * Context: interrupt.
Eric Moore635374e2009-03-09 01:21:12 -06004270 *
4271 * Return nothing.
4272 */
4273static void
4274_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4275{
Eric Moore635374e2009-03-09 01:21:12 -06004276 struct scsi_target *starget;
4277 struct MPT2SAS_TARGET *sas_target_priv_data;
4278 Mpi2EventNotificationReply_t *event_reply;
4279 Mpi2EventDataSasDeviceStatusChange_t *event_data;
4280 struct _sas_device *sas_device;
4281 ssize_t sz;
4282 unsigned long flags;
4283
4284 /* only handle non-raid devices */
4285 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4286 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4287 if (!sas_device) {
4288 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4289 return;
4290 }
4291 starget = sas_device->starget;
4292 sas_target_priv_data = starget->hostdata;
4293
4294 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
4295 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
4296 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4297 return;
4298 }
4299 starget_printk(KERN_WARNING, starget, "predicted fault\n");
4300 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4301
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05304302 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
4303 _scsih_send_event_to_turn_on_fault_led(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06004304
4305 /* insert into event log */
4306 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
4307 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
4308 event_reply = kzalloc(sz, GFP_KERNEL);
4309 if (!event_reply) {
4310 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4311 ioc->name, __FILE__, __LINE__, __func__);
4312 return;
4313 }
4314
4315 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
4316 event_reply->Event =
4317 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4318 event_reply->MsgLength = sz/4;
4319 event_reply->EventDataLength =
4320 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
4321 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
4322 event_reply->EventData;
4323 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4324 event_data->ASC = 0x5D;
4325 event_data->DevHandle = cpu_to_le16(handle);
4326 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4327 mpt2sas_ctl_add_to_event_log(ioc, event_reply);
4328 kfree(event_reply);
4329}
4330
4331/**
Eric Moored5d135b2009-05-18 13:02:08 -06004332 * _scsih_io_done - scsi request callback
Eric Moore635374e2009-03-09 01:21:12 -06004333 * @ioc: per adapter object
4334 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304335 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -06004336 * @reply: reply message frame(lower 32bit addr)
4337 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304338 * Callback handler when using _scsih_qcmd.
Eric Moore635374e2009-03-09 01:21:12 -06004339 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304340 * Return 1 meaning mf should be freed from _base_interrupt
4341 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -06004342 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304343static u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304344_scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -06004345{
4346 Mpi2SCSIIORequest_t *mpi_request;
4347 Mpi2SCSIIOReply_t *mpi_reply;
4348 struct scsi_cmnd *scmd;
4349 u16 ioc_status;
4350 u32 xfer_cnt;
4351 u8 scsi_state;
4352 u8 scsi_status;
4353 u32 log_info;
4354 struct MPT2SAS_DEVICE *sas_device_priv_data;
Kashyap, Desai9982f592009-09-23 17:23:07 +05304355 u32 response_code = 0;
Kashyap, Desai82a45252011-07-05 12:40:23 +05304356 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06004357
4358 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
Kashyap, Desaiec07a052011-01-05 17:54:32 +05304359 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -06004360 if (scmd == NULL)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304361 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06004362
4363 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
4364
4365 if (mpi_reply == NULL) {
4366 scmd->result = DID_OK << 16;
4367 goto out;
4368 }
4369
4370 sas_device_priv_data = scmd->device->hostdata;
4371 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4372 sas_device_priv_data->sas_target->deleted) {
4373 scmd->result = DID_NO_CONNECT << 16;
4374 goto out;
4375 }
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304376 /*
4377 * WARPDRIVE: If direct_io is set then it is directIO,
4378 * the failed direct I/O should be redirected to volume
4379 */
4380 if (_scsih_scsi_direct_io_get(ioc, smid)) {
Kashyap, Desai82a45252011-07-05 12:40:23 +05304381 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4382 ioc->scsi_lookup[smid - 1].scmd = scmd;
4383 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304384 _scsih_scsi_direct_io_set(ioc, smid, 0);
4385 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4386 mpi_request->DevHandle =
4387 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4388 mpt2sas_base_put_smid_scsi_io(ioc, smid,
4389 sas_device_priv_data->sas_target->handle);
4390 return 0;
4391 }
4392
Eric Moore635374e2009-03-09 01:21:12 -06004393
4394 /* turning off TLR */
Kashyap, Desai9982f592009-09-23 17:23:07 +05304395 scsi_state = mpi_reply->SCSIState;
4396 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4397 response_code =
4398 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
Eric Moore635374e2009-03-09 01:21:12 -06004399 if (!sas_device_priv_data->tlr_snoop_check) {
4400 sas_device_priv_data->tlr_snoop_check++;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05304401 /* Make sure Device is not raid volume.
4402 * We do not expose raid functionality to upper layer for warpdrive.
4403 */
4404 if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
Kashyap, Desai3ed21522010-02-17 16:08:36 +05304405 sas_is_tlr_enabled(scmd->device) &&
Kashyap, Desai84f0b042009-12-16 18:56:28 +05304406 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
4407 sas_disable_tlr(scmd->device);
4408 sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
4409 }
Eric Moore635374e2009-03-09 01:21:12 -06004410 }
4411
4412 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
4413 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
4414 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
4415 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4416 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4417 else
4418 log_info = 0;
4419 ioc_status &= MPI2_IOCSTATUS_MASK;
Eric Moore635374e2009-03-09 01:21:12 -06004420 scsi_status = mpi_reply->SCSIStatus;
4421
4422 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4423 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4424 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4425 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4426 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4427 }
4428
4429 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4430 struct sense_info data;
4431 const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
4432 smid);
Eric Moore0d04df92009-04-21 15:38:43 -06004433 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
Eric Moore635374e2009-03-09 01:21:12 -06004434 le32_to_cpu(mpi_reply->SenseCount));
Eric Moore0d04df92009-04-21 15:38:43 -06004435 memcpy(scmd->sense_buffer, sense_data, sz);
Eric Moore635374e2009-03-09 01:21:12 -06004436 _scsih_normalize_sense(scmd->sense_buffer, &data);
4437 /* failure prediction threshold exceeded */
4438 if (data.asc == 0x5D)
4439 _scsih_smart_predicted_fault(ioc,
4440 le16_to_cpu(mpi_reply->DevHandle));
4441 }
4442
4443 switch (ioc_status) {
4444 case MPI2_IOCSTATUS_BUSY:
4445 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4446 scmd->result = SAM_STAT_BUSY;
4447 break;
4448
4449 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4450 scmd->result = DID_NO_CONNECT << 16;
4451 break;
4452
4453 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4454 if (sas_device_priv_data->block) {
Kashyap, Desaie4e7c7e2009-09-23 17:33:14 +05304455 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4456 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06004457 }
Eric Moore635374e2009-03-09 01:21:12 -06004458 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4459 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4460 scmd->result = DID_RESET << 16;
4461 break;
4462
4463 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4464 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4465 scmd->result = DID_SOFT_ERROR << 16;
4466 else
4467 scmd->result = (DID_OK << 16) | scsi_status;
4468 break;
4469
4470 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4471 scmd->result = (DID_OK << 16) | scsi_status;
4472
4473 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4474 break;
4475
4476 if (xfer_cnt < scmd->underflow) {
4477 if (scsi_status == SAM_STAT_BUSY)
4478 scmd->result = SAM_STAT_BUSY;
4479 else
4480 scmd->result = DID_SOFT_ERROR << 16;
4481 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4482 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4483 scmd->result = DID_SOFT_ERROR << 16;
4484 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4485 scmd->result = DID_RESET << 16;
4486 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4487 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4488 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4489 scmd->result = (DRIVER_SENSE << 24) |
4490 SAM_STAT_CHECK_CONDITION;
4491 scmd->sense_buffer[0] = 0x70;
4492 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4493 scmd->sense_buffer[12] = 0x20;
4494 scmd->sense_buffer[13] = 0;
4495 }
4496 break;
4497
4498 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4499 scsi_set_resid(scmd, 0);
4500 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4501 case MPI2_IOCSTATUS_SUCCESS:
4502 scmd->result = (DID_OK << 16) | scsi_status;
Kashyap, Desai9982f592009-09-23 17:23:07 +05304503 if (response_code ==
4504 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4505 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4506 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
Eric Moore635374e2009-03-09 01:21:12 -06004507 scmd->result = DID_SOFT_ERROR << 16;
4508 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4509 scmd->result = DID_RESET << 16;
4510 break;
4511
Eric Moore3c621b32009-05-18 12:59:41 -06004512 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4513 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4514 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4515 _scsih_eedp_error_handling(scmd, ioc_status);
4516 break;
Eric Moore635374e2009-03-09 01:21:12 -06004517 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4518 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4519 case MPI2_IOCSTATUS_INVALID_SGL:
4520 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4521 case MPI2_IOCSTATUS_INVALID_FIELD:
4522 case MPI2_IOCSTATUS_INVALID_STATE:
4523 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4524 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4525 default:
4526 scmd->result = DID_SOFT_ERROR << 16;
4527 break;
4528
4529 }
4530
4531#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4532 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4533 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
4534#endif
4535
4536 out:
4537 scsi_dma_unmap(scmd);
4538 scmd->scsi_done(scmd);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05304539 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06004540}
4541
4542/**
Eric Moore635374e2009-03-09 01:21:12 -06004543 * _scsih_sas_host_refresh - refreshing sas host object contents
4544 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06004545 * Context: user
4546 *
4547 * During port enable, fw will send topology events for every device. Its
4548 * possible that the handles may change from the previous setting, so this
4549 * code keeping handles updating if changed.
4550 *
4551 * Return nothing.
4552 */
4553static void
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304554_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
Eric Moore635374e2009-03-09 01:21:12 -06004555{
4556 u16 sz;
4557 u16 ioc_status;
4558 int i;
4559 Mpi2ConfigReply_t mpi_reply;
4560 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304561 u16 attached_handle;
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304562 u8 link_rate;
Eric Moore635374e2009-03-09 01:21:12 -06004563
4564 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
4565 "updating handles for sas_host(0x%016llx)\n",
4566 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4567
4568 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4569 * sizeof(Mpi2SasIOUnit0PhyData_t));
4570 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4571 if (!sas_iounit_pg0) {
4572 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4573 ioc->name, __FILE__, __LINE__, __func__);
4574 return;
4575 }
Eric Moore635374e2009-03-09 01:21:12 -06004576
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304577 if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4578 sas_iounit_pg0, sz)) != 0)
4579 goto out;
4580 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4581 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4582 goto out;
4583 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304584 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304585 if (i == 0)
4586 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4587 PhyData[0].ControllerDevHandle);
4588 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4589 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4590 AttachedDevHandle);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304591 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4592 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304593 mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304594 attached_handle, i, link_rate);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304595 }
Eric Moore635374e2009-03-09 01:21:12 -06004596 out:
4597 kfree(sas_iounit_pg0);
4598}
4599
4600/**
4601 * _scsih_sas_host_add - create sas host object
4602 * @ioc: per adapter object
4603 *
4604 * Creating host side data object, stored in ioc->sas_hba
4605 *
4606 * Return nothing.
4607 */
4608static void
4609_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
4610{
4611 int i;
4612 Mpi2ConfigReply_t mpi_reply;
4613 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4614 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4615 Mpi2SasPhyPage0_t phy_pg0;
4616 Mpi2SasDevicePage0_t sas_device_pg0;
4617 Mpi2SasEnclosurePage0_t enclosure_pg0;
4618 u16 ioc_status;
4619 u16 sz;
4620 u16 device_missing_delay;
4621
4622 mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
4623 if (!ioc->sas_hba.num_phys) {
4624 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4625 ioc->name, __FILE__, __LINE__, __func__);
4626 return;
4627 }
4628
4629 /* sas_iounit page 0 */
4630 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
4631 sizeof(Mpi2SasIOUnit0PhyData_t));
4632 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4633 if (!sas_iounit_pg0) {
4634 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4635 ioc->name, __FILE__, __LINE__, __func__);
4636 return;
4637 }
4638 if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4639 sas_iounit_pg0, sz))) {
4640 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4641 ioc->name, __FILE__, __LINE__, __func__);
4642 goto out;
4643 }
4644 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4645 MPI2_IOCSTATUS_MASK;
4646 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4647 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4648 ioc->name, __FILE__, __LINE__, __func__);
4649 goto out;
4650 }
4651
4652 /* sas_iounit page 1 */
4653 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
4654 sizeof(Mpi2SasIOUnit1PhyData_t));
4655 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
4656 if (!sas_iounit_pg1) {
4657 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4658 ioc->name, __FILE__, __LINE__, __func__);
4659 goto out;
4660 }
4661 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
4662 sas_iounit_pg1, sz))) {
4663 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4664 ioc->name, __FILE__, __LINE__, __func__);
4665 goto out;
4666 }
4667 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4668 MPI2_IOCSTATUS_MASK;
4669 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4670 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4671 ioc->name, __FILE__, __LINE__, __func__);
4672 goto out;
4673 }
4674
4675 ioc->io_missing_delay =
4676 le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay);
4677 device_missing_delay =
4678 le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay);
4679 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
4680 ioc->device_missing_delay = (device_missing_delay &
4681 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
4682 else
4683 ioc->device_missing_delay = device_missing_delay &
4684 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
4685
4686 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
4687 ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
4688 sizeof(struct _sas_phy), GFP_KERNEL);
4689 if (!ioc->sas_hba.phy) {
4690 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4691 ioc->name, __FILE__, __LINE__, __func__);
4692 goto out;
4693 }
4694 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4695 if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
4696 i))) {
4697 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4698 ioc->name, __FILE__, __LINE__, __func__);
4699 goto out;
4700 }
4701 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4702 MPI2_IOCSTATUS_MASK;
4703 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4704 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4705 ioc->name, __FILE__, __LINE__, __func__);
4706 goto out;
4707 }
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304708
4709 if (i == 0)
4710 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4711 PhyData[0].ControllerDevHandle);
4712 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
Eric Moore635374e2009-03-09 01:21:12 -06004713 ioc->sas_hba.phy[i].phy_id = i;
4714 mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
4715 phy_pg0, ioc->sas_hba.parent_dev);
4716 }
4717 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304718 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
Eric Moore635374e2009-03-09 01:21:12 -06004719 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4720 ioc->name, __FILE__, __LINE__, __func__);
4721 goto out;
4722 }
Eric Moore635374e2009-03-09 01:21:12 -06004723 ioc->sas_hba.enclosure_handle =
4724 le16_to_cpu(sas_device_pg0.EnclosureHandle);
4725 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4726 printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), "
4727 "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle,
4728 (unsigned long long) ioc->sas_hba.sas_address,
4729 ioc->sas_hba.num_phys) ;
4730
4731 if (ioc->sas_hba.enclosure_handle) {
4732 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4733 &enclosure_pg0,
4734 MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4735 ioc->sas_hba.enclosure_handle))) {
4736 ioc->sas_hba.enclosure_logical_id =
4737 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4738 }
4739 }
4740
4741 out:
4742 kfree(sas_iounit_pg1);
4743 kfree(sas_iounit_pg0);
4744}
4745
4746/**
4747 * _scsih_expander_add - creating expander object
4748 * @ioc: per adapter object
4749 * @handle: expander handle
4750 *
4751 * Creating expander object, stored in ioc->sas_expander_list.
4752 *
4753 * Return 0 for success, else error.
4754 */
4755static int
4756_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
4757{
4758 struct _sas_node *sas_expander;
4759 Mpi2ConfigReply_t mpi_reply;
4760 Mpi2ExpanderPage0_t expander_pg0;
4761 Mpi2ExpanderPage1_t expander_pg1;
4762 Mpi2SasEnclosurePage0_t enclosure_pg0;
4763 u32 ioc_status;
4764 u16 parent_handle;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05304765 u64 sas_address, sas_address_parent = 0;
Eric Moore635374e2009-03-09 01:21:12 -06004766 int i;
4767 unsigned long flags;
Kashyap, Desai20f58952009-08-07 19:34:26 +05304768 struct _sas_port *mpt2sas_port = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06004769 int rc = 0;
4770
4771 if (!handle)
4772 return -1;
4773
Eric Moore3cb54692010-07-08 14:44:34 -06004774 if (ioc->shost_recovery || ioc->pci_error_recovery)
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05304775 return -1;
4776
Eric Moore635374e2009-03-09 01:21:12 -06004777 if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
4778 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
4779 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4780 ioc->name, __FILE__, __LINE__, __func__);
4781 return -1;
4782 }
4783
4784 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4785 MPI2_IOCSTATUS_MASK;
4786 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4787 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4788 ioc->name, __FILE__, __LINE__, __func__);
4789 return -1;
4790 }
4791
4792 /* handle out of order topology events */
4793 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304794 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
4795 != 0) {
4796 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4797 ioc->name, __FILE__, __LINE__, __func__);
4798 return -1;
4799 }
4800 if (sas_address_parent != ioc->sas_hba.sas_address) {
Eric Moore635374e2009-03-09 01:21:12 -06004801 spin_lock_irqsave(&ioc->sas_node_lock, flags);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304802 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
4803 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06004804 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4805 if (!sas_expander) {
4806 rc = _scsih_expander_add(ioc, parent_handle);
4807 if (rc != 0)
4808 return rc;
4809 }
4810 }
4811
Eric Moore635374e2009-03-09 01:21:12 -06004812 spin_lock_irqsave(&ioc->sas_node_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05304813 sas_address = le64_to_cpu(expander_pg0.SASAddress);
Eric Moore635374e2009-03-09 01:21:12 -06004814 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
4815 sas_address);
4816 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4817
4818 if (sas_expander)
4819 return 0;
4820
4821 sas_expander = kzalloc(sizeof(struct _sas_node),
4822 GFP_KERNEL);
4823 if (!sas_expander) {
4824 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4825 ioc->name, __FILE__, __LINE__, __func__);
4826 return -1;
4827 }
4828
4829 sas_expander->handle = handle;
4830 sas_expander->num_phys = expander_pg0.NumPhys;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304831 sas_expander->sas_address_parent = sas_address_parent;
Eric Moore635374e2009-03-09 01:21:12 -06004832 sas_expander->sas_address = sas_address;
4833
4834 printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
4835 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304836 handle, parent_handle, (unsigned long long)
Eric Moore635374e2009-03-09 01:21:12 -06004837 sas_expander->sas_address, sas_expander->num_phys);
4838
4839 if (!sas_expander->num_phys)
4840 goto out_fail;
4841 sas_expander->phy = kcalloc(sas_expander->num_phys,
4842 sizeof(struct _sas_phy), GFP_KERNEL);
4843 if (!sas_expander->phy) {
4844 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4845 ioc->name, __FILE__, __LINE__, __func__);
4846 rc = -1;
4847 goto out_fail;
4848 }
4849
4850 INIT_LIST_HEAD(&sas_expander->sas_port_list);
4851 mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304852 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06004853 if (!mpt2sas_port) {
4854 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4855 ioc->name, __FILE__, __LINE__, __func__);
4856 rc = -1;
4857 goto out_fail;
4858 }
4859 sas_expander->parent_dev = &mpt2sas_port->rphy->dev;
4860
4861 for (i = 0 ; i < sas_expander->num_phys ; i++) {
4862 if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
4863 &expander_pg1, i, handle))) {
4864 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4865 ioc->name, __FILE__, __LINE__, __func__);
Kashyap, Desai20f58952009-08-07 19:34:26 +05304866 rc = -1;
4867 goto out_fail;
Eric Moore635374e2009-03-09 01:21:12 -06004868 }
4869 sas_expander->phy[i].handle = handle;
4870 sas_expander->phy[i].phy_id = i;
Kashyap, Desai20f58952009-08-07 19:34:26 +05304871
4872 if ((mpt2sas_transport_add_expander_phy(ioc,
4873 &sas_expander->phy[i], expander_pg1,
4874 sas_expander->parent_dev))) {
4875 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
4876 ioc->name, __FILE__, __LINE__, __func__);
4877 rc = -1;
4878 goto out_fail;
4879 }
Eric Moore635374e2009-03-09 01:21:12 -06004880 }
4881
4882 if (sas_expander->enclosure_handle) {
4883 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4884 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4885 sas_expander->enclosure_handle))) {
4886 sas_expander->enclosure_logical_id =
4887 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4888 }
4889 }
4890
4891 _scsih_expander_node_add(ioc, sas_expander);
4892 return 0;
4893
4894 out_fail:
4895
Kashyap, Desai20f58952009-08-07 19:34:26 +05304896 if (mpt2sas_port)
4897 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304898 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06004899 kfree(sas_expander);
4900 return rc;
4901}
4902
4903/**
Kashyap, Desai744090d2009-10-05 15:56:56 +05304904 * _scsih_done - scsih callback handler.
4905 * @ioc: per adapter object
4906 * @smid: system request message index
4907 * @msix_index: MSIX table index supplied by the OS
4908 * @reply: reply message frame(lower 32bit addr)
4909 *
4910 * Callback handler when sending internal generated message frames.
4911 * The callback index passed is `ioc->scsih_cb_idx`
4912 *
4913 * Return 1 meaning mf should be freed from _base_interrupt
4914 * 0 means the mf is freed from this function.
4915 */
4916static u8
4917_scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4918{
4919 MPI2DefaultReply_t *mpi_reply;
4920
4921 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
4922 if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED)
4923 return 1;
4924 if (ioc->scsih_cmds.smid != smid)
4925 return 1;
4926 ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE;
4927 if (mpi_reply) {
4928 memcpy(ioc->scsih_cmds.reply, mpi_reply,
4929 mpi_reply->MsgLength*4);
4930 ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID;
4931 }
4932 ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING;
4933 complete(&ioc->scsih_cmds.done);
4934 return 1;
4935}
4936
4937/**
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304938 * mpt2sas_expander_remove - removing expander object
Eric Moore635374e2009-03-09 01:21:12 -06004939 * @ioc: per adapter object
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304940 * @sas_address: expander sas_address
Eric Moore635374e2009-03-09 01:21:12 -06004941 *
4942 * Return nothing.
4943 */
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304944void
4945mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
Eric Moore635374e2009-03-09 01:21:12 -06004946{
4947 struct _sas_node *sas_expander;
4948 unsigned long flags;
4949
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05304950 if (ioc->shost_recovery)
4951 return;
4952
Eric Moore635374e2009-03-09 01:21:12 -06004953 spin_lock_irqsave(&ioc->sas_node_lock, flags);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05304954 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
4955 sas_address);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05304956 if (!sas_expander) {
4957 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4958 return;
4959 }
4960 list_del(&sas_expander->list);
Eric Moore635374e2009-03-09 01:21:12 -06004961 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4962 _scsih_expander_node_remove(ioc, sas_expander);
4963}
4964
4965/**
Kashyap, Desaib4344272010-03-17 16:24:14 +05304966 * _scsih_check_access_status - check access flags
4967 * @ioc: per adapter object
4968 * @sas_address: sas address
4969 * @handle: sas device handle
4970 * @access_flags: errors returned during discovery of the device
4971 *
4972 * Return 0 for success, else failure
4973 */
4974static u8
4975_scsih_check_access_status(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
4976 u16 handle, u8 access_status)
4977{
4978 u8 rc = 1;
4979 char *desc = NULL;
4980
4981 switch (access_status) {
4982 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
4983 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
4984 rc = 0;
4985 break;
4986 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
4987 desc = "sata capability failed";
4988 break;
4989 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
4990 desc = "sata affiliation conflict";
4991 break;
4992 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
4993 desc = "route not addressable";
4994 break;
4995 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
4996 desc = "smp error not addressable";
4997 break;
4998 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
4999 desc = "device blocked";
5000 break;
5001 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
5002 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
5003 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
5004 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
5005 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
5006 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
5007 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
5008 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
5009 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
5010 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
5011 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
5012 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
5013 desc = "sata initialization failed";
5014 break;
5015 default:
5016 desc = "unknown";
5017 break;
5018 }
5019
5020 if (!rc)
5021 return 0;
5022
5023 printk(MPT2SAS_ERR_FMT "discovery errors(%s): sas_address(0x%016llx), "
5024 "handle(0x%04x)\n", ioc->name, desc,
5025 (unsigned long long)sas_address, handle);
5026 return rc;
5027}
5028
5029static void
5030_scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
5031{
5032 Mpi2ConfigReply_t mpi_reply;
5033 Mpi2SasDevicePage0_t sas_device_pg0;
5034 struct _sas_device *sas_device;
5035 u32 ioc_status;
5036 unsigned long flags;
5037 u64 sas_address;
5038 struct scsi_target *starget;
5039 struct MPT2SAS_TARGET *sas_target_priv_data;
5040 u32 device_info;
5041
5042 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5043 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
5044 return;
5045
5046 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
5047 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
5048 return;
5049
5050 /* check if this is end device */
5051 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5052 if (!(_scsih_is_end_device(device_info)))
5053 return;
5054
5055 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5056 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5057 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5058 sas_address);
5059
5060 if (!sas_device) {
5061 printk(MPT2SAS_ERR_FMT "device is not present "
5062 "handle(0x%04x), no sas_device!!!\n", ioc->name, handle);
5063 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5064 return;
5065 }
5066
5067 if (unlikely(sas_device->handle != handle)) {
5068 starget = sas_device->starget;
5069 sas_target_priv_data = starget->hostdata;
5070 starget_printk(KERN_INFO, starget, "handle changed from(0x%04x)"
5071 " to (0x%04x)!!!\n", sas_device->handle, handle);
5072 sas_target_priv_data->handle = handle;
5073 sas_device->handle = handle;
5074 }
5075 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5076
5077 /* check if device is present */
5078 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5079 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5080 printk(MPT2SAS_ERR_FMT "device is not present "
5081 "handle(0x%04x), flags!!!\n", ioc->name, handle);
5082 return;
5083 }
5084
5085 /* check if there were any issues with discovery */
5086 if (_scsih_check_access_status(ioc, sas_address, handle,
5087 sas_device_pg0.AccessStatus))
5088 return;
5089 _scsih_ublock_io_device(ioc, handle);
5090
5091}
5092
5093/**
Eric Moore635374e2009-03-09 01:21:12 -06005094 * _scsih_add_device - creating sas device object
5095 * @ioc: per adapter object
5096 * @handle: sas device handle
5097 * @phy_num: phy number end device attached to
5098 * @is_pd: is this hidden raid component
5099 *
5100 * Creating end device object, stored in ioc->sas_device_list.
5101 *
5102 * Returns 0 for success, non-zero for failure.
5103 */
5104static int
5105_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
5106{
5107 Mpi2ConfigReply_t mpi_reply;
5108 Mpi2SasDevicePage0_t sas_device_pg0;
5109 Mpi2SasEnclosurePage0_t enclosure_pg0;
5110 struct _sas_device *sas_device;
5111 u32 ioc_status;
5112 __le64 sas_address;
5113 u32 device_info;
5114 unsigned long flags;
5115
5116 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5117 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5118 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5119 ioc->name, __FILE__, __LINE__, __func__);
5120 return -1;
5121 }
5122
5123 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5124 MPI2_IOCSTATUS_MASK;
5125 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5126 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5127 ioc->name, __FILE__, __LINE__, __func__);
5128 return -1;
5129 }
5130
Kashyap, Desaib4344272010-03-17 16:24:14 +05305131 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5132
Eric Moore635374e2009-03-09 01:21:12 -06005133 /* check if device is present */
5134 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5135 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5136 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5137 ioc->name, __FILE__, __LINE__, __func__);
5138 printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n",
5139 ioc->name, le16_to_cpu(sas_device_pg0.Flags));
5140 return -1;
5141 }
5142
Kashyap, Desaib4344272010-03-17 16:24:14 +05305143 /* check if there were any issues with discovery */
5144 if (_scsih_check_access_status(ioc, sas_address, handle,
5145 sas_device_pg0.AccessStatus))
Eric Moore635374e2009-03-09 01:21:12 -06005146 return -1;
Eric Moore635374e2009-03-09 01:21:12 -06005147
5148 /* check if this is end device */
5149 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5150 if (!(_scsih_is_end_device(device_info))) {
5151 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5152 ioc->name, __FILE__, __LINE__, __func__);
5153 return -1;
5154 }
5155
Eric Moore635374e2009-03-09 01:21:12 -06005156
5157 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5158 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5159 sas_address);
5160 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5161
Kashyap, Desaib4344272010-03-17 16:24:14 +05305162 if (sas_device)
Eric Moore635374e2009-03-09 01:21:12 -06005163 return 0;
Eric Moore635374e2009-03-09 01:21:12 -06005164
5165 sas_device = kzalloc(sizeof(struct _sas_device),
5166 GFP_KERNEL);
5167 if (!sas_device) {
5168 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5169 ioc->name, __FILE__, __LINE__, __func__);
5170 return -1;
5171 }
5172
5173 sas_device->handle = handle;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305174 if (_scsih_get_sas_address(ioc, le16_to_cpu
5175 (sas_device_pg0.ParentDevHandle),
5176 &sas_device->sas_address_parent) != 0)
5177 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5178 ioc->name, __FILE__, __LINE__, __func__);
Eric Moore635374e2009-03-09 01:21:12 -06005179 sas_device->enclosure_handle =
5180 le16_to_cpu(sas_device_pg0.EnclosureHandle);
5181 sas_device->slot =
5182 le16_to_cpu(sas_device_pg0.Slot);
5183 sas_device->device_info = device_info;
5184 sas_device->sas_address = sas_address;
Kashyap, Desai7fbae672010-06-17 13:45:17 +05305185 sas_device->phy = sas_device_pg0.PhyNum;
Eric Moore635374e2009-03-09 01:21:12 -06005186
5187 /* get enclosure_logical_id */
Kashyap, Desai15052c92009-08-07 19:33:17 +05305188 if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
5189 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5190 sas_device->enclosure_handle)))
Eric Moore635374e2009-03-09 01:21:12 -06005191 sas_device->enclosure_logical_id =
5192 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
Eric Moore635374e2009-03-09 01:21:12 -06005193
5194 /* get device name */
5195 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5196
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305197 if (ioc->wait_for_discovery_to_complete)
Eric Moore635374e2009-03-09 01:21:12 -06005198 _scsih_sas_device_init_add(ioc, sas_device);
5199 else
5200 _scsih_sas_device_add(ioc, sas_device);
5201
5202 return 0;
5203}
5204
5205/**
Kashyap, Desai1278b112010-03-09 17:34:13 +05305206 * _scsih_remove_device - removing sas device object
5207 * @ioc: per adapter object
5208 * @sas_device_delete: the sas_device object
5209 *
5210 * Return nothing.
5211 */
5212static void
5213_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
5214 struct _sas_device *sas_device)
5215{
5216 struct _sas_device sas_device_backup;
5217 struct MPT2SAS_TARGET *sas_target_priv_data;
Kashyap, Desai34a03be2009-08-20 13:23:19 +05305218
Kashyap, Desai1278b112010-03-09 17:34:13 +05305219 if (!sas_device)
5220 return;
Eric Moore635374e2009-03-09 01:21:12 -06005221
Kashyap, Desai1278b112010-03-09 17:34:13 +05305222 memcpy(&sas_device_backup, sas_device, sizeof(struct _sas_device));
Eric Moore635374e2009-03-09 01:21:12 -06005223 _scsih_sas_device_remove(ioc, sas_device);
5224
Kashyap, Desai1278b112010-03-09 17:34:13 +05305225 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: "
5226 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
5227 sas_device_backup.handle, (unsigned long long)
5228 sas_device_backup.sas_address));
5229
5230 if (sas_device_backup.starget && sas_device_backup.starget->hostdata) {
5231 sas_target_priv_data = sas_device_backup.starget->hostdata;
5232 sas_target_priv_data->deleted = 1;
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305233 _scsih_ublock_io_device(ioc, sas_device_backup.handle);
5234 sas_target_priv_data->handle =
5235 MPT2SAS_INVALID_DEVICE_HANDLE;
Kashyap, Desai1278b112010-03-09 17:34:13 +05305236 }
5237
Kashyap, Desai1278b112010-03-09 17:34:13 +05305238 _scsih_ublock_io_device(ioc, sas_device_backup.handle);
5239
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05305240 if (!ioc->hide_drives)
5241 mpt2sas_transport_port_remove(ioc,
5242 sas_device_backup.sas_address,
5243 sas_device_backup.sas_address_parent);
Kashyap, Desai1278b112010-03-09 17:34:13 +05305244
5245 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
5246 "(0x%016llx)\n", ioc->name, sas_device_backup.handle,
5247 (unsigned long long) sas_device_backup.sas_address);
5248
5249 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: "
5250 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
5251 sas_device_backup.handle, (unsigned long long)
5252 sas_device_backup.sas_address));
Eric Moore635374e2009-03-09 01:21:12 -06005253}
5254
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305255/**
5256 * mpt2sas_device_remove - removing device object
5257 * @ioc: per adapter object
5258 * @sas_address: expander sas_address
5259 *
5260 * Return nothing.
5261 */
5262void
5263mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
5264{
5265 struct _sas_device *sas_device;
5266 unsigned long flags;
5267
5268 if (ioc->shost_recovery)
5269 return;
5270
5271 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5272 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5273 sas_address);
5274 if (!sas_device) {
5275 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5276 return;
5277 }
5278 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5279 _scsih_remove_device(ioc, sas_device);
5280}
5281
Eric Moore635374e2009-03-09 01:21:12 -06005282#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5283/**
5284 * _scsih_sas_topology_change_event_debug - debug for topology event
5285 * @ioc: per adapter object
5286 * @event_data: event data payload
5287 * Context: user.
5288 */
5289static void
5290_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5291 Mpi2EventDataSasTopologyChangeList_t *event_data)
5292{
5293 int i;
5294 u16 handle;
5295 u16 reason_code;
5296 u8 phy_number;
5297 char *status_str = NULL;
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305298 u8 link_rate, prev_link_rate;
Eric Moore635374e2009-03-09 01:21:12 -06005299
5300 switch (event_data->ExpStatus) {
5301 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
5302 status_str = "add";
5303 break;
5304 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
5305 status_str = "remove";
5306 break;
5307 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305308 case 0:
Eric Moore635374e2009-03-09 01:21:12 -06005309 status_str = "responding";
5310 break;
5311 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
5312 status_str = "remove delay";
5313 break;
5314 default:
5315 status_str = "unknown status";
5316 break;
5317 }
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305318 printk(MPT2SAS_INFO_FMT "sas topology change: (%s)\n",
Eric Moore635374e2009-03-09 01:21:12 -06005319 ioc->name, status_str);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305320 printk(KERN_INFO "\thandle(0x%04x), enclosure_handle(0x%04x) "
Eric Moore635374e2009-03-09 01:21:12 -06005321 "start_phy(%02d), count(%d)\n",
5322 le16_to_cpu(event_data->ExpanderDevHandle),
5323 le16_to_cpu(event_data->EnclosureHandle),
5324 event_data->StartPhyNum, event_data->NumEntries);
5325 for (i = 0; i < event_data->NumEntries; i++) {
5326 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5327 if (!handle)
5328 continue;
5329 phy_number = event_data->StartPhyNum + i;
5330 reason_code = event_data->PHY[i].PhyStatus &
5331 MPI2_EVENT_SAS_TOPO_RC_MASK;
5332 switch (reason_code) {
5333 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305334 status_str = "target add";
Eric Moore635374e2009-03-09 01:21:12 -06005335 break;
5336 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305337 status_str = "target remove";
Eric Moore635374e2009-03-09 01:21:12 -06005338 break;
5339 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305340 status_str = "delay target remove";
Eric Moore635374e2009-03-09 01:21:12 -06005341 break;
5342 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305343 status_str = "link rate change";
Eric Moore635374e2009-03-09 01:21:12 -06005344 break;
5345 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305346 status_str = "target responding";
Eric Moore635374e2009-03-09 01:21:12 -06005347 break;
5348 default:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305349 status_str = "unknown";
Eric Moore635374e2009-03-09 01:21:12 -06005350 break;
5351 }
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305352 link_rate = event_data->PHY[i].LinkRate >> 4;
5353 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305354 printk(KERN_INFO "\tphy(%02d), attached_handle(0x%04x): %s:"
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305355 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5356 handle, status_str, link_rate, prev_link_rate);
5357
Eric Moore635374e2009-03-09 01:21:12 -06005358 }
5359}
5360#endif
5361
5362/**
5363 * _scsih_sas_topology_change_event - handle topology changes
5364 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305365 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005366 * Context: user.
5367 *
5368 */
5369static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305370_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
Eric Moore635374e2009-03-09 01:21:12 -06005371 struct fw_event_work *fw_event)
5372{
5373 int i;
5374 u16 parent_handle, handle;
5375 u16 reason_code;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305376 u8 phy_number, max_phys;
Eric Moore635374e2009-03-09 01:21:12 -06005377 struct _sas_node *sas_expander;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305378 struct _sas_device *sas_device;
5379 u64 sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06005380 unsigned long flags;
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305381 u8 link_rate, prev_link_rate;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305382 Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
Eric Moore635374e2009-03-09 01:21:12 -06005383
5384#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5385 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5386 _scsih_sas_topology_change_event_debug(ioc, event_data);
5387#endif
5388
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305389 if (ioc->remove_host || ioc->pci_error_recovery)
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305390 return;
5391
Eric Moore635374e2009-03-09 01:21:12 -06005392 if (!ioc->sas_hba.num_phys)
5393 _scsih_sas_host_add(ioc);
5394 else
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305395 _scsih_sas_host_refresh(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06005396
5397 if (fw_event->ignore) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305398 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring expander "
Eric Moore635374e2009-03-09 01:21:12 -06005399 "event\n", ioc->name));
5400 return;
5401 }
5402
5403 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5404
5405 /* handle expander add */
5406 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5407 if (_scsih_expander_add(ioc, parent_handle) != 0)
5408 return;
5409
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305410 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5411 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
5412 parent_handle);
5413 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305414 if (sas_expander) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305415 sas_address = sas_expander->sas_address;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305416 max_phys = sas_expander->num_phys;
5417 } else if (parent_handle < ioc->sas_hba.num_phys) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305418 sas_address = ioc->sas_hba.sas_address;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305419 max_phys = ioc->sas_hba.num_phys;
5420 } else
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305421 return;
5422
Eric Moore635374e2009-03-09 01:21:12 -06005423 /* handle siblings events */
5424 for (i = 0; i < event_data->NumEntries; i++) {
5425 if (fw_event->ignore) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305426 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring "
Eric Moore635374e2009-03-09 01:21:12 -06005427 "expander event\n", ioc->name));
5428 return;
5429 }
Eric Moore3cb54692010-07-08 14:44:34 -06005430 if (ioc->shost_recovery || ioc->remove_host ||
5431 ioc->pci_error_recovery)
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05305432 return;
Kashyap, Desai308609c2009-09-14 11:07:23 +05305433 phy_number = event_data->StartPhyNum + i;
Kashyap, Desaib41c09d2010-11-13 04:40:51 +05305434 if (phy_number >= max_phys)
5435 continue;
Kashyap, Desai308609c2009-09-14 11:07:23 +05305436 reason_code = event_data->PHY[i].PhyStatus &
5437 MPI2_EVENT_SAS_TOPO_RC_MASK;
5438 if ((event_data->PHY[i].PhyStatus &
5439 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5440 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
Eric Moore635374e2009-03-09 01:21:12 -06005441 continue;
5442 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5443 if (!handle)
5444 continue;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305445 link_rate = event_data->PHY[i].LinkRate >> 4;
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305446 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
Eric Moore635374e2009-03-09 01:21:12 -06005447 switch (reason_code) {
5448 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305449
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305450 if (ioc->shost_recovery)
5451 break;
5452
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305453 if (link_rate == prev_link_rate)
5454 break;
5455
5456 mpt2sas_transport_update_links(ioc, sas_address,
5457 handle, phy_number, link_rate);
5458
Kashyap, Desaib4344272010-03-17 16:24:14 +05305459 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5460 break;
5461
5462 _scsih_check_device(ioc, handle);
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305463 break;
Eric Moore635374e2009-03-09 01:21:12 -06005464 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305465
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05305466 if (ioc->shost_recovery)
5467 break;
5468
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305469 mpt2sas_transport_update_links(ioc, sas_address,
5470 handle, phy_number, link_rate);
5471
Kashyap, Desaie7d59c12009-09-23 17:36:52 +05305472 _scsih_add_device(ioc, handle, phy_number, 0);
Eric Moore635374e2009-03-09 01:21:12 -06005473 break;
5474 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305475
5476 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5477 sas_device = _scsih_sas_device_find_by_handle(ioc,
5478 handle);
5479 if (!sas_device) {
5480 spin_unlock_irqrestore(&ioc->sas_device_lock,
5481 flags);
5482 break;
5483 }
5484 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5485 _scsih_remove_device(ioc, sas_device);
Eric Moore635374e2009-03-09 01:21:12 -06005486 break;
5487 }
5488 }
5489
5490 /* handle expander removal */
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05305491 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5492 sas_expander)
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05305493 mpt2sas_expander_remove(ioc, sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06005494
5495}
5496
5497#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5498/**
5499 * _scsih_sas_device_status_change_event_debug - debug for device event
5500 * @event_data: event data payload
5501 * Context: user.
5502 *
5503 * Return nothing.
5504 */
5505static void
5506_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5507 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5508{
5509 char *reason_str = NULL;
5510
5511 switch (event_data->ReasonCode) {
5512 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5513 reason_str = "smart data";
5514 break;
5515 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5516 reason_str = "unsupported device discovered";
5517 break;
5518 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5519 reason_str = "internal device reset";
5520 break;
5521 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5522 reason_str = "internal task abort";
5523 break;
5524 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5525 reason_str = "internal task abort set";
5526 break;
5527 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5528 reason_str = "internal clear task set";
5529 break;
5530 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5531 reason_str = "internal query task";
5532 break;
5533 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5534 reason_str = "sata init failure";
5535 break;
5536 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5537 reason_str = "internal device reset complete";
5538 break;
5539 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5540 reason_str = "internal task abort complete";
5541 break;
5542 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5543 reason_str = "internal async notification";
5544 break;
Kashyap, Desaiec6c2b42009-09-23 17:31:01 +05305545 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5546 reason_str = "expander reduced functionality";
5547 break;
5548 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5549 reason_str = "expander reduced functionality complete";
5550 break;
Eric Moore635374e2009-03-09 01:21:12 -06005551 default:
5552 reason_str = "unknown reason";
5553 break;
5554 }
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305555 printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305556 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5557 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5558 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5559 le16_to_cpu(event_data->TaskTag));
Eric Moore635374e2009-03-09 01:21:12 -06005560 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305561 printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06005562 event_data->ASC, event_data->ASCQ);
5563 printk(KERN_INFO "\n");
5564}
5565#endif
5566
5567/**
5568 * _scsih_sas_device_status_change_event - handle device status change
5569 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305570 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005571 * Context: user.
5572 *
5573 * Return nothing.
5574 */
5575static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305576_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
5577 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005578{
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305579 struct MPT2SAS_TARGET *target_priv_data;
5580 struct _sas_device *sas_device;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05305581 u64 sas_address;
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305582 unsigned long flags;
5583 Mpi2EventDataSasDeviceStatusChange_t *event_data =
5584 fw_event->event_data;
5585
Eric Moore635374e2009-03-09 01:21:12 -06005586#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5587 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305588 _scsih_sas_device_status_change_event_debug(ioc,
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305589 event_data);
Eric Moore635374e2009-03-09 01:21:12 -06005590#endif
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305591
Kashyap, Desaiefe82a12011-01-04 11:34:17 +05305592 /* In MPI Revision K (0xC), the internal device reset complete was
5593 * implemented, so avoid setting tm_busy flag for older firmware.
5594 */
5595 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
5596 return;
5597
Kashyap, Desaif891dcf2010-03-17 16:22:21 +05305598 if (event_data->ReasonCode !=
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305599 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
Kashyap, Desaif891dcf2010-03-17 16:22:21 +05305600 event_data->ReasonCode !=
5601 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
Kashyap, Desai8ffc4572009-09-23 17:35:41 +05305602 return;
5603
5604 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5605 sas_address = le64_to_cpu(event_data->SASAddress);
5606 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5607 sas_address);
5608 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5609
5610 if (!sas_device || !sas_device->starget)
5611 return;
5612
5613 target_priv_data = sas_device->starget->hostdata;
5614 if (!target_priv_data)
5615 return;
5616
5617 if (event_data->ReasonCode ==
5618 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
5619 target_priv_data->tm_busy = 1;
5620 else
5621 target_priv_data->tm_busy = 0;
Eric Moore635374e2009-03-09 01:21:12 -06005622}
5623
5624#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5625/**
5626 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event
5627 * @ioc: per adapter object
5628 * @event_data: event data payload
5629 * Context: user.
5630 *
5631 * Return nothing.
5632 */
5633static void
5634_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5635 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
5636{
5637 char *reason_str = NULL;
5638
5639 switch (event_data->ReasonCode) {
5640 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
5641 reason_str = "enclosure add";
5642 break;
5643 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
5644 reason_str = "enclosure remove";
5645 break;
5646 default:
5647 reason_str = "unknown reason";
5648 break;
5649 }
5650
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305651 printk(MPT2SAS_INFO_FMT "enclosure status change: (%s)\n"
Eric Moore635374e2009-03-09 01:21:12 -06005652 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
5653 " number slots(%d)\n", ioc->name, reason_str,
5654 le16_to_cpu(event_data->EnclosureHandle),
5655 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
5656 le16_to_cpu(event_data->StartSlot));
5657}
5658#endif
5659
5660/**
5661 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
5662 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305663 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005664 * Context: user.
5665 *
5666 * Return nothing.
5667 */
5668static void
5669_scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305670 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005671{
5672#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5673 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5674 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305675 fw_event->event_data);
Eric Moore635374e2009-03-09 01:21:12 -06005676#endif
5677}
5678
5679/**
5680 * _scsih_sas_broadcast_primative_event - handle broadcast events
5681 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305682 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005683 * Context: user.
5684 *
5685 * Return nothing.
5686 */
5687static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305688_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5689 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005690{
5691 struct scsi_cmnd *scmd;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305692 struct scsi_device *sdev;
Eric Moore635374e2009-03-09 01:21:12 -06005693 u16 smid, handle;
5694 u32 lun;
5695 struct MPT2SAS_DEVICE *sas_device_priv_data;
5696 u32 termination_count;
5697 u32 query_count;
5698 Mpi2SCSITaskManagementReply_t *mpi_reply;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305699 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
Kashyap, Desai463217b2009-10-05 15:53:06 +05305700 u16 ioc_status;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305701 unsigned long flags;
5702 int r;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305703 u8 max_retries = 0;
5704 u8 task_abort_retries;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305705
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305706 mutex_lock(&ioc->tm_cmds.mutex);
5707 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
5708 "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
5709 event_data->PortWidth));
5710
5711 _scsih_block_io_all_device(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06005712
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305713 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305714 mpi_reply = ioc->tm_cmds.reply;
5715broadcast_aen_retry:
5716
5717 /* sanity checks for retrying this loop */
5718 if (max_retries++ == 5) {
5719 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
5720 ioc->name, __func__));
5721 goto out;
5722 } else if (max_retries > 1)
5723 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
5724 ioc->name, __func__, max_retries - 1));
5725
Eric Moore635374e2009-03-09 01:21:12 -06005726 termination_count = 0;
5727 query_count = 0;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05305728 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305729 if (ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305730 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06005731 scmd = _scsih_scsi_lookup_get(ioc, smid);
5732 if (!scmd)
5733 continue;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305734 sdev = scmd->device;
5735 sas_device_priv_data = sdev->hostdata;
Eric Moore635374e2009-03-09 01:21:12 -06005736 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
5737 continue;
5738 /* skip hidden raid components */
5739 if (sas_device_priv_data->sas_target->flags &
5740 MPT_TARGET_FLAGS_RAID_COMPONENT)
5741 continue;
5742 /* skip volumes */
5743 if (sas_device_priv_data->sas_target->flags &
5744 MPT_TARGET_FLAGS_VOLUME)
5745 continue;
5746
5747 handle = sas_device_priv_data->sas_target->handle;
5748 lun = sas_device_priv_data->lun;
5749 query_count++;
5750
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305751 if (ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305752 goto out;
5753
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305754 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305755 r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
5756 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
5757 TM_MUTEX_OFF);
5758 if (r == FAILED) {
5759 sdev_printk(KERN_WARNING, sdev,
5760 "mpt2sas_scsih_issue_tm: FAILED when sending "
5761 "QUERY_TASK: scmd(%p)\n", scmd);
5762 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5763 goto broadcast_aen_retry;
5764 }
Kashyap, Desai463217b2009-10-05 15:53:06 +05305765 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
5766 & MPI2_IOCSTATUS_MASK;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305767 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5768 sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
5769 "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
5770 scmd);
5771 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5772 goto broadcast_aen_retry;
5773 }
5774
5775 /* see if IO is still owned by IOC and target */
5776 if (mpi_reply->ResponseCode ==
Eric Moore635374e2009-03-09 01:21:12 -06005777 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5778 mpi_reply->ResponseCode ==
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305779 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305780 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06005781 continue;
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305782 }
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305783 task_abort_retries = 0;
5784 tm_retry:
5785 if (task_abort_retries++ == 60) {
5786 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
5787 "%s: ABORT_TASK: giving up\n", ioc->name,
5788 __func__));
5789 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5790 goto broadcast_aen_retry;
5791 }
5792
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305793 if (ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305794 goto out_no_lock;
5795
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305796 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5797 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305798 scmd->serial_number, TM_MUTEX_OFF);
5799 if (r == FAILED) {
5800 sdev_printk(KERN_WARNING, sdev,
5801 "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305802 "scmd(%p)\n", scmd);
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305803 goto tm_retry;
5804 }
5805
5806 if (task_abort_retries > 1)
5807 sdev_printk(KERN_WARNING, sdev,
5808 "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
5809 " scmd(%p)\n",
5810 task_abort_retries - 1, scmd);
5811
Eric Moore635374e2009-03-09 01:21:12 -06005812 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
Kashyap, Desaiec07a052011-01-05 17:54:32 +05305813 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06005814 }
Eric Moore635374e2009-03-09 01:21:12 -06005815
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305816 if (ioc->broadcast_aen_pending) {
5817 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
5818 " pending AEN\n", ioc->name, __func__));
5819 ioc->broadcast_aen_pending = 0;
5820 goto broadcast_aen_retry;
5821 }
5822
5823 out:
5824 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5825 out_no_lock:
5826
5827 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06005828 "%s - exit, query_count = %d termination_count = %d\n",
5829 ioc->name, __func__, query_count, termination_count));
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305830
5831 ioc->broadcast_aen_busy = 0;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305832 if (!ioc->shost_recovery)
Kashyap, Desaif93213d2011-06-14 10:56:43 +05305833 _scsih_ublock_io_all_device(ioc);
5834 mutex_unlock(&ioc->tm_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06005835}
5836
5837/**
5838 * _scsih_sas_discovery_event - handle discovery events
5839 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305840 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06005841 * Context: user.
5842 *
5843 * Return nothing.
5844 */
5845static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305846_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
5847 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06005848{
Kashyap, Desai7b936b02009-09-25 11:44:41 +05305849 Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
5850
Eric Moore635374e2009-03-09 01:21:12 -06005851#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5852 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05305853 printk(MPT2SAS_INFO_FMT "discovery event: (%s)", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06005854 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
5855 "start" : "stop");
5856 if (event_data->DiscoveryStatus)
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05305857 printk("discovery_status(0x%08x)",
5858 le32_to_cpu(event_data->DiscoveryStatus));
Eric Moore635374e2009-03-09 01:21:12 -06005859 printk("\n");
5860 }
5861#endif
5862
5863 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
5864 !ioc->sas_hba.num_phys)
5865 _scsih_sas_host_add(ioc);
5866}
5867
5868/**
5869 * _scsih_reprobe_lun - reprobing lun
5870 * @sdev: scsi device struct
5871 * @no_uld_attach: sdev->no_uld_attach flag setting
5872 *
5873 **/
5874static void
5875_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
5876{
5877 int rc;
5878
5879 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
5880 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
5881 sdev->no_uld_attach ? "hidding" : "exposing");
5882 rc = scsi_device_reprobe(sdev);
5883}
5884
5885/**
5886 * _scsih_reprobe_target - reprobing target
5887 * @starget: scsi target struct
5888 * @no_uld_attach: sdev->no_uld_attach flag setting
5889 *
5890 * Note: no_uld_attach flag determines whether the disk device is attached
5891 * to block layer. A value of `1` means to not attach.
5892 **/
5893static void
5894_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
5895{
5896 struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata;
5897
5898 if (no_uld_attach)
5899 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
5900 else
5901 sas_target_priv_data->flags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
5902
5903 starget_for_each_device(starget, no_uld_attach ? (void *)1 : NULL,
5904 _scsih_reprobe_lun);
5905}
5906/**
5907 * _scsih_sas_volume_add - add new volume
5908 * @ioc: per adapter object
5909 * @element: IR config element data
5910 * Context: user.
5911 *
5912 * Return nothing.
5913 */
5914static void
5915_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
5916 Mpi2EventIrConfigElement_t *element)
5917{
5918 struct _raid_device *raid_device;
5919 unsigned long flags;
5920 u64 wwid;
5921 u16 handle = le16_to_cpu(element->VolDevHandle);
5922 int rc;
5923
Eric Moore635374e2009-03-09 01:21:12 -06005924 mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
5925 if (!wwid) {
5926 printk(MPT2SAS_ERR_FMT
5927 "failure at %s:%d/%s()!\n", ioc->name,
5928 __FILE__, __LINE__, __func__);
5929 return;
5930 }
5931
5932 spin_lock_irqsave(&ioc->raid_device_lock, flags);
5933 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
5934 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
5935
5936 if (raid_device)
5937 return;
5938
5939 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
5940 if (!raid_device) {
5941 printk(MPT2SAS_ERR_FMT
5942 "failure at %s:%d/%s()!\n", ioc->name,
5943 __FILE__, __LINE__, __func__);
5944 return;
5945 }
5946
5947 raid_device->id = ioc->sas_id++;
5948 raid_device->channel = RAID_CHANNEL;
5949 raid_device->handle = handle;
5950 raid_device->wwid = wwid;
5951 _scsih_raid_device_add(ioc, raid_device);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05305952 if (!ioc->wait_for_discovery_to_complete) {
Eric Moore635374e2009-03-09 01:21:12 -06005953 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
5954 raid_device->id, 0);
5955 if (rc)
5956 _scsih_raid_device_remove(ioc, raid_device);
5957 } else
5958 _scsih_determine_boot_device(ioc, raid_device, 1);
5959}
5960
5961/**
5962 * _scsih_sas_volume_delete - delete volume
5963 * @ioc: per adapter object
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05305964 * @handle: volume device handle
Eric Moore635374e2009-03-09 01:21:12 -06005965 * Context: user.
5966 *
5967 * Return nothing.
5968 */
5969static void
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05305970_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle)
Eric Moore635374e2009-03-09 01:21:12 -06005971{
5972 struct _raid_device *raid_device;
Eric Moore635374e2009-03-09 01:21:12 -06005973 unsigned long flags;
5974 struct MPT2SAS_TARGET *sas_target_priv_data;
5975
Eric Moore635374e2009-03-09 01:21:12 -06005976 spin_lock_irqsave(&ioc->raid_device_lock, flags);
5977 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
5978 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
5979 if (!raid_device)
5980 return;
5981 if (raid_device->starget) {
5982 sas_target_priv_data = raid_device->starget->hostdata;
5983 sas_target_priv_data->deleted = 1;
5984 scsi_remove_target(&raid_device->starget->dev);
5985 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05305986 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
5987 "(0x%016llx)\n", ioc->name, raid_device->handle,
5988 (unsigned long long) raid_device->wwid);
Eric Moore635374e2009-03-09 01:21:12 -06005989 _scsih_raid_device_remove(ioc, raid_device);
5990}
5991
5992/**
5993 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
5994 * @ioc: per adapter object
5995 * @element: IR config element data
5996 * Context: user.
5997 *
5998 * Return nothing.
5999 */
6000static void
6001_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
6002 Mpi2EventIrConfigElement_t *element)
6003{
6004 struct _sas_device *sas_device;
6005 unsigned long flags;
6006 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6007
6008 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6009 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6010 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6011 if (!sas_device)
6012 return;
6013
6014 /* exposing raid component */
6015 sas_device->volume_handle = 0;
6016 sas_device->volume_wwid = 0;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306017 clear_bit(handle, ioc->pd_handles);
Eric Moore635374e2009-03-09 01:21:12 -06006018 _scsih_reprobe_target(sas_device->starget, 0);
6019}
6020
6021/**
6022 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
6023 * @ioc: per adapter object
6024 * @element: IR config element data
6025 * Context: user.
6026 *
6027 * Return nothing.
6028 */
6029static void
6030_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
6031 Mpi2EventIrConfigElement_t *element)
6032{
6033 struct _sas_device *sas_device;
6034 unsigned long flags;
6035 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6036
6037 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6038 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6039 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6040 if (!sas_device)
6041 return;
6042
6043 /* hiding raid component */
6044 mpt2sas_config_get_volume_handle(ioc, handle,
6045 &sas_device->volume_handle);
6046 mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle,
6047 &sas_device->volume_wwid);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306048 set_bit(handle, ioc->pd_handles);
Eric Moore635374e2009-03-09 01:21:12 -06006049 _scsih_reprobe_target(sas_device->starget, 1);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306050
Eric Moore635374e2009-03-09 01:21:12 -06006051}
6052
6053/**
6054 * _scsih_sas_pd_delete - delete pd component
6055 * @ioc: per adapter object
6056 * @element: IR config element data
6057 * Context: user.
6058 *
6059 * Return nothing.
6060 */
6061static void
6062_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
6063 Mpi2EventIrConfigElement_t *element)
6064{
6065 struct _sas_device *sas_device;
6066 unsigned long flags;
6067 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6068
6069 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6070 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6071 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6072 if (!sas_device)
6073 return;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306074 _scsih_remove_device(ioc, sas_device);
Eric Moore635374e2009-03-09 01:21:12 -06006075}
6076
6077/**
6078 * _scsih_sas_pd_add - remove pd component
6079 * @ioc: per adapter object
6080 * @element: IR config element data
6081 * Context: user.
6082 *
6083 * Return nothing.
6084 */
6085static void
6086_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
6087 Mpi2EventIrConfigElement_t *element)
6088{
6089 struct _sas_device *sas_device;
6090 unsigned long flags;
6091 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
Kashyap, Desai62727a72009-08-07 19:35:18 +05306092 Mpi2ConfigReply_t mpi_reply;
6093 Mpi2SasDevicePage0_t sas_device_pg0;
6094 u32 ioc_status;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306095 u64 sas_address;
6096 u16 parent_handle;
Eric Moore635374e2009-03-09 01:21:12 -06006097
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306098 set_bit(handle, ioc->pd_handles);
6099
Eric Moore635374e2009-03-09 01:21:12 -06006100 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6101 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6102 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306103 if (sas_device)
Kashyap, Desai62727a72009-08-07 19:35:18 +05306104 return;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306105
6106 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
6107 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
6108 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6109 ioc->name, __FILE__, __LINE__, __func__);
6110 return;
6111 }
6112
6113 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6114 MPI2_IOCSTATUS_MASK;
6115 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6116 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6117 ioc->name, __FILE__, __LINE__, __func__);
6118 return;
6119 }
6120
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306121 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6122 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6123 mpt2sas_transport_update_links(ioc, sas_address, handle,
6124 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
Kashyap, Desai62727a72009-08-07 19:35:18 +05306125
6126 _scsih_add_device(ioc, handle, 0, 1);
Eric Moore635374e2009-03-09 01:21:12 -06006127}
6128
6129#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
6130/**
6131 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
6132 * @ioc: per adapter object
6133 * @event_data: event data payload
6134 * Context: user.
6135 *
6136 * Return nothing.
6137 */
6138static void
6139_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
6140 Mpi2EventDataIrConfigChangeList_t *event_data)
6141{
6142 Mpi2EventIrConfigElement_t *element;
6143 u8 element_type;
6144 int i;
6145 char *reason_str = NULL, *element_str = NULL;
6146
6147 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6148
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05306149 printk(MPT2SAS_INFO_FMT "raid config change: (%s), elements(%d)\n",
Eric Moore635374e2009-03-09 01:21:12 -06006150 ioc->name, (le32_to_cpu(event_data->Flags) &
6151 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
6152 "foreign" : "native", event_data->NumElements);
6153 for (i = 0; i < event_data->NumElements; i++, element++) {
6154 switch (element->ReasonCode) {
6155 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6156 reason_str = "add";
6157 break;
6158 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6159 reason_str = "remove";
6160 break;
6161 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
6162 reason_str = "no change";
6163 break;
6164 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6165 reason_str = "hide";
6166 break;
6167 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6168 reason_str = "unhide";
6169 break;
6170 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6171 reason_str = "volume_created";
6172 break;
6173 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6174 reason_str = "volume_deleted";
6175 break;
6176 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6177 reason_str = "pd_created";
6178 break;
6179 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6180 reason_str = "pd_deleted";
6181 break;
6182 default:
6183 reason_str = "unknown reason";
6184 break;
6185 }
6186 element_type = le16_to_cpu(element->ElementFlags) &
6187 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
6188 switch (element_type) {
6189 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
6190 element_str = "volume";
6191 break;
6192 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
6193 element_str = "phys disk";
6194 break;
6195 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
6196 element_str = "hot spare";
6197 break;
6198 default:
6199 element_str = "unknown element";
6200 break;
6201 }
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05306202 printk(KERN_INFO "\t(%s:%s), vol handle(0x%04x), "
Eric Moore635374e2009-03-09 01:21:12 -06006203 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
6204 reason_str, le16_to_cpu(element->VolDevHandle),
6205 le16_to_cpu(element->PhysDiskDevHandle),
6206 element->PhysDiskNum);
6207 }
6208}
6209#endif
6210
6211/**
6212 * _scsih_sas_ir_config_change_event - handle ir configuration change events
6213 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306214 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006215 * Context: user.
6216 *
6217 * Return nothing.
6218 */
6219static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306220_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
6221 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006222{
6223 Mpi2EventIrConfigElement_t *element;
6224 int i;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306225 u8 foreign_config;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306226 Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
Eric Moore635374e2009-03-09 01:21:12 -06006227
6228#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306229 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6230 && !ioc->hide_ir_msg)
Eric Moore635374e2009-03-09 01:21:12 -06006231 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6232
6233#endif
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306234
6235 if (ioc->shost_recovery)
6236 return;
6237
Kashyap, Desai62727a72009-08-07 19:35:18 +05306238 foreign_config = (le32_to_cpu(event_data->Flags) &
6239 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
Eric Moore635374e2009-03-09 01:21:12 -06006240
6241 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6242 for (i = 0; i < event_data->NumElements; i++, element++) {
6243
6244 switch (element->ReasonCode) {
6245 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6246 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
Kashyap, Desai62727a72009-08-07 19:35:18 +05306247 if (!foreign_config)
6248 _scsih_sas_volume_add(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006249 break;
6250 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6251 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
Kashyap, Desai62727a72009-08-07 19:35:18 +05306252 if (!foreign_config)
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306253 _scsih_sas_volume_delete(ioc,
6254 le16_to_cpu(element->VolDevHandle));
Eric Moore635374e2009-03-09 01:21:12 -06006255 break;
6256 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306257 if (!ioc->is_warpdrive)
6258 _scsih_sas_pd_hide(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006259 break;
6260 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306261 if (!ioc->is_warpdrive)
6262 _scsih_sas_pd_expose(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006263 break;
6264 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306265 if (!ioc->is_warpdrive)
6266 _scsih_sas_pd_add(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006267 break;
6268 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306269 if (!ioc->is_warpdrive)
6270 _scsih_sas_pd_delete(ioc, element);
Eric Moore635374e2009-03-09 01:21:12 -06006271 break;
6272 }
6273 }
6274}
6275
6276/**
6277 * _scsih_sas_ir_volume_event - IR volume event
6278 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306279 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006280 * Context: user.
6281 *
6282 * Return nothing.
6283 */
6284static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306285_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
6286 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006287{
6288 u64 wwid;
6289 unsigned long flags;
6290 struct _raid_device *raid_device;
6291 u16 handle;
6292 u32 state;
6293 int rc;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306294 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
Eric Moore635374e2009-03-09 01:21:12 -06006295
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306296 if (ioc->shost_recovery)
6297 return;
6298
Eric Moore635374e2009-03-09 01:21:12 -06006299 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6300 return;
6301
6302 handle = le16_to_cpu(event_data->VolDevHandle);
6303 state = le32_to_cpu(event_data->NewValue);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306304 if (!ioc->hide_ir_msg)
6305 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
6306 "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
6307 le32_to_cpu(event_data->PreviousValue), state));
Eric Moore635374e2009-03-09 01:21:12 -06006308
Eric Moore635374e2009-03-09 01:21:12 -06006309 switch (state) {
6310 case MPI2_RAID_VOL_STATE_MISSING:
6311 case MPI2_RAID_VOL_STATE_FAILED:
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306312 _scsih_sas_volume_delete(ioc, handle);
Eric Moore635374e2009-03-09 01:21:12 -06006313 break;
6314
6315 case MPI2_RAID_VOL_STATE_ONLINE:
6316 case MPI2_RAID_VOL_STATE_DEGRADED:
6317 case MPI2_RAID_VOL_STATE_OPTIMAL:
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306318
6319 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6320 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6321 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6322
Eric Moore635374e2009-03-09 01:21:12 -06006323 if (raid_device)
6324 break;
6325
6326 mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
6327 if (!wwid) {
6328 printk(MPT2SAS_ERR_FMT
6329 "failure at %s:%d/%s()!\n", ioc->name,
6330 __FILE__, __LINE__, __func__);
6331 break;
6332 }
6333
6334 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6335 if (!raid_device) {
6336 printk(MPT2SAS_ERR_FMT
6337 "failure at %s:%d/%s()!\n", ioc->name,
6338 __FILE__, __LINE__, __func__);
6339 break;
6340 }
6341
6342 raid_device->id = ioc->sas_id++;
6343 raid_device->channel = RAID_CHANNEL;
6344 raid_device->handle = handle;
6345 raid_device->wwid = wwid;
6346 _scsih_raid_device_add(ioc, raid_device);
6347 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6348 raid_device->id, 0);
6349 if (rc)
6350 _scsih_raid_device_remove(ioc, raid_device);
6351 break;
6352
6353 case MPI2_RAID_VOL_STATE_INITIALIZING:
6354 default:
6355 break;
6356 }
6357}
6358
6359/**
6360 * _scsih_sas_ir_physical_disk_event - PD event
6361 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306362 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006363 * Context: user.
6364 *
6365 * Return nothing.
6366 */
6367static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306368_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
6369 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006370{
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306371 u16 handle, parent_handle;
Eric Moore635374e2009-03-09 01:21:12 -06006372 u32 state;
6373 struct _sas_device *sas_device;
6374 unsigned long flags;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306375 Mpi2ConfigReply_t mpi_reply;
6376 Mpi2SasDevicePage0_t sas_device_pg0;
6377 u32 ioc_status;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306378 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306379 u64 sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06006380
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306381 if (ioc->shost_recovery)
6382 return;
6383
Eric Moore635374e2009-03-09 01:21:12 -06006384 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6385 return;
6386
6387 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6388 state = le32_to_cpu(event_data->NewValue);
6389
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306390 if (!ioc->hide_ir_msg)
6391 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
6392 "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
6393 le32_to_cpu(event_data->PreviousValue), state));
Eric Moore635374e2009-03-09 01:21:12 -06006394
Eric Moore635374e2009-03-09 01:21:12 -06006395 switch (state) {
Eric Moore635374e2009-03-09 01:21:12 -06006396 case MPI2_RAID_PD_STATE_ONLINE:
6397 case MPI2_RAID_PD_STATE_DEGRADED:
6398 case MPI2_RAID_PD_STATE_REBUILDING:
6399 case MPI2_RAID_PD_STATE_OPTIMAL:
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306400 case MPI2_RAID_PD_STATE_HOT_SPARE:
6401
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306402 if (!ioc->is_warpdrive)
6403 set_bit(handle, ioc->pd_handles);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306404
6405 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6406 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6407 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6408
6409 if (sas_device)
Kashyap, Desai62727a72009-08-07 19:35:18 +05306410 return;
Kashyap, Desai62727a72009-08-07 19:35:18 +05306411
6412 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6413 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6414 handle))) {
6415 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6416 ioc->name, __FILE__, __LINE__, __func__);
6417 return;
6418 }
6419
6420 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6421 MPI2_IOCSTATUS_MASK;
6422 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6423 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6424 ioc->name, __FILE__, __LINE__, __func__);
6425 return;
6426 }
6427
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306428 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6429 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6430 mpt2sas_transport_update_links(ioc, sas_address, handle,
6431 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
Kashyap, Desai62727a72009-08-07 19:35:18 +05306432
6433 _scsih_add_device(ioc, handle, 0, 1);
6434
Eric Moore635374e2009-03-09 01:21:12 -06006435 break;
6436
Kashyap, Desai62727a72009-08-07 19:35:18 +05306437 case MPI2_RAID_PD_STATE_OFFLINE:
Eric Moore635374e2009-03-09 01:21:12 -06006438 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6439 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
Eric Moore635374e2009-03-09 01:21:12 -06006440 default:
6441 break;
6442 }
6443}
6444
6445#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
6446/**
6447 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6448 * @ioc: per adapter object
6449 * @event_data: event data payload
6450 * Context: user.
6451 *
6452 * Return nothing.
6453 */
6454static void
6455_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
6456 Mpi2EventDataIrOperationStatus_t *event_data)
6457{
6458 char *reason_str = NULL;
6459
6460 switch (event_data->RAIDOperation) {
6461 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6462 reason_str = "resync";
6463 break;
6464 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6465 reason_str = "online capacity expansion";
6466 break;
6467 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6468 reason_str = "consistency check";
6469 break;
Kashyap, Desaiec6c2b42009-09-23 17:31:01 +05306470 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6471 reason_str = "background init";
6472 break;
6473 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
6474 reason_str = "make data consistent";
Eric Moore635374e2009-03-09 01:21:12 -06006475 break;
6476 }
6477
Kashyap, Desaiec6c2b42009-09-23 17:31:01 +05306478 if (!reason_str)
6479 return;
6480
Eric Moore635374e2009-03-09 01:21:12 -06006481 printk(MPT2SAS_INFO_FMT "raid operational status: (%s)"
6482 "\thandle(0x%04x), percent complete(%d)\n",
6483 ioc->name, reason_str,
6484 le16_to_cpu(event_data->VolDevHandle),
6485 event_data->PercentComplete);
6486}
6487#endif
6488
6489/**
6490 * _scsih_sas_ir_operation_status_event - handle RAID operation events
6491 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306492 * @fw_event: The fw_event_work object
Eric Moore635374e2009-03-09 01:21:12 -06006493 * Context: user.
6494 *
6495 * Return nothing.
6496 */
6497static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306498_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
6499 struct fw_event_work *fw_event)
Eric Moore635374e2009-03-09 01:21:12 -06006500{
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306501 Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
6502 static struct _raid_device *raid_device;
6503 unsigned long flags;
6504 u16 handle;
6505
Eric Moore635374e2009-03-09 01:21:12 -06006506#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306507 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6508 && !ioc->hide_ir_msg)
Kashyap, Desai7b936b02009-09-25 11:44:41 +05306509 _scsih_sas_ir_operation_status_event_debug(ioc,
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306510 event_data);
Eric Moore635374e2009-03-09 01:21:12 -06006511#endif
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05306512
6513 /* code added for raid transport support */
6514 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
6515
6516 handle = le16_to_cpu(event_data->VolDevHandle);
6517
6518 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6519 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6520 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6521
6522 if (!raid_device)
6523 return;
6524
6525 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC)
6526 raid_device->percent_complete =
6527 event_data->PercentComplete;
6528 }
Eric Moore635374e2009-03-09 01:21:12 -06006529}
6530
6531/**
Kashyap, Desai14695852010-03-30 10:52:44 +05306532 * _scsih_prep_device_scan - initialize parameters prior to device scan
6533 * @ioc: per adapter object
6534 *
6535 * Set the deleted flag prior to device scan. If the device is found during
6536 * the scan, then we clear the deleted flag.
6537 */
6538static void
6539_scsih_prep_device_scan(struct MPT2SAS_ADAPTER *ioc)
6540{
6541 struct MPT2SAS_DEVICE *sas_device_priv_data;
6542 struct scsi_device *sdev;
6543
6544 shost_for_each_device(sdev, ioc->shost) {
6545 sas_device_priv_data = sdev->hostdata;
6546 if (sas_device_priv_data && sas_device_priv_data->sas_target)
6547 sas_device_priv_data->sas_target->deleted = 1;
6548 }
6549}
6550
6551/**
Eric Moore635374e2009-03-09 01:21:12 -06006552 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
6553 * @ioc: per adapter object
6554 * @sas_address: sas address
6555 * @slot: enclosure slot id
6556 * @handle: device handle
6557 *
6558 * After host reset, find out whether devices are still responding.
6559 * Used in _scsi_remove_unresponsive_sas_devices.
6560 *
6561 * Return nothing.
6562 */
6563static void
6564_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
6565 u16 slot, u16 handle)
6566{
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306567 struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06006568 struct scsi_target *starget;
6569 struct _sas_device *sas_device;
6570 unsigned long flags;
6571
6572 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6573 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
6574 if (sas_device->sas_address == sas_address &&
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306575 sas_device->slot == slot) {
Eric Moore635374e2009-03-09 01:21:12 -06006576 sas_device->responding = 1;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05306577 starget = sas_device->starget;
Kashyap, Desai14695852010-03-30 10:52:44 +05306578 if (starget && starget->hostdata) {
6579 sas_target_priv_data = starget->hostdata;
6580 sas_target_priv_data->tm_busy = 0;
6581 sas_target_priv_data->deleted = 0;
6582 } else
6583 sas_target_priv_data = NULL;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306584 if (starget)
6585 starget_printk(KERN_INFO, starget,
6586 "handle(0x%04x), sas_addr(0x%016llx), "
6587 "enclosure logical id(0x%016llx), "
6588 "slot(%d)\n", handle,
6589 (unsigned long long)sas_device->sas_address,
6590 (unsigned long long)
6591 sas_device->enclosure_logical_id,
6592 sas_device->slot);
Eric Moore635374e2009-03-09 01:21:12 -06006593 if (sas_device->handle == handle)
6594 goto out;
6595 printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
6596 sas_device->handle);
6597 sas_device->handle = handle;
Kashyap, Desai14695852010-03-30 10:52:44 +05306598 if (sas_target_priv_data)
6599 sas_target_priv_data->handle = handle;
Eric Moore635374e2009-03-09 01:21:12 -06006600 goto out;
6601 }
6602 }
6603 out:
6604 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6605}
6606
6607/**
6608 * _scsih_search_responding_sas_devices -
6609 * @ioc: per adapter object
6610 *
6611 * After host reset, find out whether devices are still responding.
6612 * If not remove.
6613 *
6614 * Return nothing.
6615 */
6616static void
6617_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6618{
6619 Mpi2SasDevicePage0_t sas_device_pg0;
6620 Mpi2ConfigReply_t mpi_reply;
6621 u16 ioc_status;
6622 __le64 sas_address;
6623 u16 handle;
6624 u32 device_info;
6625 u16 slot;
6626
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306627 printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006628
6629 if (list_empty(&ioc->sas_device_list))
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306630 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006631
6632 handle = 0xFFFF;
6633 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6634 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6635 handle))) {
6636 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6637 MPI2_IOCSTATUS_MASK;
6638 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6639 break;
6640 handle = le16_to_cpu(sas_device_pg0.DevHandle);
6641 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
6642 if (!(_scsih_is_end_device(device_info)))
6643 continue;
6644 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
6645 slot = le16_to_cpu(sas_device_pg0.Slot);
6646 _scsih_mark_responding_sas_device(ioc, sas_address, slot,
6647 handle);
6648 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306649out:
6650 printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
6651 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006652}
6653
6654/**
6655 * _scsih_mark_responding_raid_device - mark a raid_device as responding
6656 * @ioc: per adapter object
6657 * @wwid: world wide identifier for raid volume
6658 * @handle: device handle
6659 *
6660 * After host reset, find out whether devices are still responding.
6661 * Used in _scsi_remove_unresponsive_raid_devices.
6662 *
6663 * Return nothing.
6664 */
6665static void
6666_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
6667 u16 handle)
6668{
6669 struct MPT2SAS_TARGET *sas_target_priv_data;
6670 struct scsi_target *starget;
6671 struct _raid_device *raid_device;
6672 unsigned long flags;
6673
6674 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6675 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
6676 if (raid_device->wwid == wwid && raid_device->starget) {
Kashyap, Desai14695852010-03-30 10:52:44 +05306677 starget = raid_device->starget;
6678 if (starget && starget->hostdata) {
6679 sas_target_priv_data = starget->hostdata;
6680 sas_target_priv_data->deleted = 0;
6681 } else
6682 sas_target_priv_data = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06006683 raid_device->responding = 1;
6684 starget_printk(KERN_INFO, raid_device->starget,
6685 "handle(0x%04x), wwid(0x%016llx)\n", handle,
6686 (unsigned long long)raid_device->wwid);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306687 /*
6688 * WARPDRIVE: The handles of the PDs might have changed
6689 * across the host reset so re-initialize the
6690 * required data for Direct IO
6691 */
6692 _scsih_init_warpdrive_properties(ioc, raid_device);
Eric Moore635374e2009-03-09 01:21:12 -06006693 if (raid_device->handle == handle)
6694 goto out;
6695 printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
6696 raid_device->handle);
6697 raid_device->handle = handle;
Kashyap, Desai14695852010-03-30 10:52:44 +05306698 if (sas_target_priv_data)
6699 sas_target_priv_data->handle = handle;
Eric Moore635374e2009-03-09 01:21:12 -06006700 goto out;
6701 }
6702 }
6703 out:
6704 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6705}
6706
6707/**
6708 * _scsih_search_responding_raid_devices -
6709 * @ioc: per adapter object
6710 *
6711 * After host reset, find out whether devices are still responding.
6712 * If not remove.
6713 *
6714 * Return nothing.
6715 */
6716static void
6717_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
6718{
6719 Mpi2RaidVolPage1_t volume_pg1;
Kashyap, Desaid417d1c2010-06-17 13:48:10 +05306720 Mpi2RaidVolPage0_t volume_pg0;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306721 Mpi2RaidPhysDiskPage0_t pd_pg0;
Eric Moore635374e2009-03-09 01:21:12 -06006722 Mpi2ConfigReply_t mpi_reply;
6723 u16 ioc_status;
6724 u16 handle;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306725 u8 phys_disk_num;
Eric Moore635374e2009-03-09 01:21:12 -06006726
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306727 if (!ioc->ir_firmware)
6728 return;
6729
6730 printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
6731 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006732
6733 if (list_empty(&ioc->raid_device_list))
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306734 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006735
6736 handle = 0xFFFF;
6737 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
6738 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
6739 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6740 MPI2_IOCSTATUS_MASK;
6741 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6742 break;
6743 handle = le16_to_cpu(volume_pg1.DevHandle);
Kashyap, Desaid417d1c2010-06-17 13:48:10 +05306744
6745 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
6746 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
6747 sizeof(Mpi2RaidVolPage0_t)))
6748 continue;
6749
6750 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
6751 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
6752 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
6753 _scsih_mark_responding_raid_device(ioc,
6754 le64_to_cpu(volume_pg1.WWID), handle);
Eric Moore635374e2009-03-09 01:21:12 -06006755 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306756
6757 /* refresh the pd_handles */
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306758 if (!ioc->is_warpdrive) {
6759 phys_disk_num = 0xFF;
6760 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
6761 while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
6762 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
6763 phys_disk_num))) {
6764 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6765 MPI2_IOCSTATUS_MASK;
6766 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6767 break;
6768 phys_disk_num = pd_pg0.PhysDiskNum;
6769 handle = le16_to_cpu(pd_pg0.DevHandle);
6770 set_bit(handle, ioc->pd_handles);
6771 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05306772 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306773out:
6774 printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
6775 "complete\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006776}
6777
6778/**
6779 * _scsih_mark_responding_expander - mark a expander as responding
6780 * @ioc: per adapter object
6781 * @sas_address: sas address
6782 * @handle:
6783 *
6784 * After host reset, find out whether devices are still responding.
6785 * Used in _scsi_remove_unresponsive_expanders.
6786 *
6787 * Return nothing.
6788 */
6789static void
6790_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
6791 u16 handle)
6792{
6793 struct _sas_node *sas_expander;
6794 unsigned long flags;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306795 int i;
Eric Moore635374e2009-03-09 01:21:12 -06006796
6797 spin_lock_irqsave(&ioc->sas_node_lock, flags);
6798 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306799 if (sas_expander->sas_address != sas_address)
6800 continue;
6801 sas_expander->responding = 1;
6802 if (sas_expander->handle == handle)
Eric Moore635374e2009-03-09 01:21:12 -06006803 goto out;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306804 printk(KERN_INFO "\texpander(0x%016llx): handle changed"
6805 " from(0x%04x) to (0x%04x)!!!\n",
6806 (unsigned long long)sas_expander->sas_address,
6807 sas_expander->handle, handle);
6808 sas_expander->handle = handle;
6809 for (i = 0 ; i < sas_expander->num_phys ; i++)
6810 sas_expander->phy[i].handle = handle;
6811 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006812 }
6813 out:
6814 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
6815}
6816
6817/**
6818 * _scsih_search_responding_expanders -
6819 * @ioc: per adapter object
6820 *
6821 * After host reset, find out whether devices are still responding.
6822 * If not remove.
6823 *
6824 * Return nothing.
6825 */
6826static void
6827_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
6828{
6829 Mpi2ExpanderPage0_t expander_pg0;
6830 Mpi2ConfigReply_t mpi_reply;
6831 u16 ioc_status;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05306832 u64 sas_address;
Eric Moore635374e2009-03-09 01:21:12 -06006833 u16 handle;
6834
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306835 printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006836
6837 if (list_empty(&ioc->sas_expander_list))
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306838 goto out;
Eric Moore635374e2009-03-09 01:21:12 -06006839
6840 handle = 0xFFFF;
6841 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
6842 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
6843
6844 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6845 MPI2_IOCSTATUS_MASK;
6846 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6847 break;
6848
6849 handle = le16_to_cpu(expander_pg0.DevHandle);
6850 sas_address = le64_to_cpu(expander_pg0.SASAddress);
6851 printk(KERN_INFO "\texpander present: handle(0x%04x), "
6852 "sas_addr(0x%016llx)\n", handle,
6853 (unsigned long long)sas_address);
6854 _scsih_mark_responding_expander(ioc, sas_address, handle);
6855 }
6856
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306857 out:
6858 printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006859}
6860
6861/**
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05306862 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
Eric Moore635374e2009-03-09 01:21:12 -06006863 * @ioc: per adapter object
6864 *
6865 * Return nothing.
6866 */
6867static void
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05306868_scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
Eric Moore635374e2009-03-09 01:21:12 -06006869{
6870 struct _sas_device *sas_device, *sas_device_next;
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05306871 struct _sas_node *sas_expander;
Eric Moore635374e2009-03-09 01:21:12 -06006872 struct _raid_device *raid_device, *raid_device_next;
Eric Moore635374e2009-03-09 01:21:12 -06006873
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306874 printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
6875 ioc->name);
Eric Moore635374e2009-03-09 01:21:12 -06006876
6877 list_for_each_entry_safe(sas_device, sas_device_next,
6878 &ioc->sas_device_list, list) {
6879 if (sas_device->responding) {
6880 sas_device->responding = 0;
6881 continue;
6882 }
6883 if (sas_device->starget)
6884 starget_printk(KERN_INFO, sas_device->starget,
6885 "removing: handle(0x%04x), sas_addr(0x%016llx), "
6886 "enclosure logical id(0x%016llx), slot(%d)\n",
6887 sas_device->handle,
6888 (unsigned long long)sas_device->sas_address,
6889 (unsigned long long)
6890 sas_device->enclosure_logical_id,
6891 sas_device->slot);
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05306892 _scsih_remove_device(ioc, sas_device);
Eric Moore635374e2009-03-09 01:21:12 -06006893 }
6894
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306895 if (!ioc->ir_firmware)
6896 goto retry_expander_search;
6897
Eric Moore635374e2009-03-09 01:21:12 -06006898 list_for_each_entry_safe(raid_device, raid_device_next,
6899 &ioc->raid_device_list, list) {
6900 if (raid_device->responding) {
6901 raid_device->responding = 0;
6902 continue;
6903 }
6904 if (raid_device->starget) {
6905 starget_printk(KERN_INFO, raid_device->starget,
6906 "removing: handle(0x%04x), wwid(0x%016llx)\n",
6907 raid_device->handle,
6908 (unsigned long long)raid_device->wwid);
6909 scsi_remove_target(&raid_device->starget->dev);
6910 }
6911 _scsih_raid_device_remove(ioc, raid_device);
6912 }
6913
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05306914 retry_expander_search:
6915 sas_expander = NULL;
6916 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
Eric Moore635374e2009-03-09 01:21:12 -06006917 if (sas_expander->responding) {
6918 sas_expander->responding = 0;
6919 continue;
6920 }
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05306921 mpt2sas_expander_remove(ioc, sas_expander->sas_address);
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05306922 goto retry_expander_search;
6923 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306924 printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
6925 ioc->name);
6926 /* unblock devices */
6927 _scsih_ublock_io_all_device(ioc);
6928}
6929
6930static void
6931_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
6932 struct _sas_node *sas_expander, u16 handle)
6933{
6934 Mpi2ExpanderPage1_t expander_pg1;
6935 Mpi2ConfigReply_t mpi_reply;
6936 int i;
6937
6938 for (i = 0 ; i < sas_expander->num_phys ; i++) {
6939 if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
6940 &expander_pg1, i, handle))) {
6941 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6942 ioc->name, __FILE__, __LINE__, __func__);
6943 return;
6944 }
6945
6946 mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
6947 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
6948 expander_pg1.NegotiatedLinkRate >> 4);
6949 }
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05306950}
6951
6952/**
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306953 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306954 * @ioc: per adapter object
6955 *
6956 * Return nothing.
6957 */
6958static void
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306959_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306960{
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306961 Mpi2ExpanderPage0_t expander_pg0;
6962 Mpi2SasDevicePage0_t sas_device_pg0;
6963 Mpi2RaidVolPage1_t volume_pg1;
6964 Mpi2RaidVolPage0_t volume_pg0;
6965 Mpi2RaidPhysDiskPage0_t pd_pg0;
6966 Mpi2EventIrConfigElement_t element;
6967 Mpi2ConfigReply_t mpi_reply;
6968 u8 phys_disk_num;
6969 u16 ioc_status;
6970 u16 handle, parent_handle;
6971 u64 sas_address;
6972 struct _sas_device *sas_device;
6973 struct _sas_node *expander_device;
6974 static struct _raid_device *raid_device;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306975
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306976 printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05306977
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05306978 _scsih_sas_host_refresh(ioc);
6979
6980 /* expanders */
6981 handle = 0xFFFF;
6982 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
6983 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
6984 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6985 MPI2_IOCSTATUS_MASK;
6986 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6987 break;
6988 handle = le16_to_cpu(expander_pg0.DevHandle);
6989 expander_device = mpt2sas_scsih_expander_find_by_sas_address(
6990 ioc, le64_to_cpu(expander_pg0.SASAddress));
6991 if (expander_device)
6992 _scsih_refresh_expander_links(ioc, expander_device,
6993 handle);
6994 else
6995 _scsih_expander_add(ioc, handle);
6996 }
6997
6998 if (!ioc->ir_firmware)
6999 goto skip_to_sas;
7000
7001 /* phys disk */
7002 phys_disk_num = 0xFF;
7003 while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7004 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7005 phys_disk_num))) {
7006 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7007 MPI2_IOCSTATUS_MASK;
7008 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7009 break;
7010 phys_disk_num = pd_pg0.PhysDiskNum;
7011 handle = le16_to_cpu(pd_pg0.DevHandle);
7012 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
7013 if (sas_device)
7014 continue;
7015 if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7016 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
7017 handle) != 0)
7018 continue;
7019 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7020 if (!_scsih_get_sas_address(ioc, parent_handle,
7021 &sas_address)) {
7022 mpt2sas_transport_update_links(ioc, sas_address,
7023 handle, sas_device_pg0.PhyNum,
7024 MPI2_SAS_NEG_LINK_RATE_1_5);
7025 set_bit(handle, ioc->pd_handles);
7026 _scsih_add_device(ioc, handle, 0, 1);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307027 }
7028 }
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307029
7030 /* volumes */
7031 handle = 0xFFFF;
7032 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7033 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7034 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7035 MPI2_IOCSTATUS_MASK;
7036 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7037 break;
7038 handle = le16_to_cpu(volume_pg1.DevHandle);
7039 raid_device = _scsih_raid_device_find_by_wwid(ioc,
7040 le64_to_cpu(volume_pg1.WWID));
7041 if (raid_device)
7042 continue;
7043 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7044 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7045 sizeof(Mpi2RaidVolPage0_t)))
7046 continue;
7047 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7048 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7049 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
7050 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
7051 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
7052 element.VolDevHandle = volume_pg1.DevHandle;
7053 _scsih_sas_volume_add(ioc, &element);
7054 }
7055 }
7056
7057 skip_to_sas:
7058
7059 /* sas devices */
7060 handle = 0xFFFF;
7061 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7062 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7063 handle))) {
7064 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7065 MPI2_IOCSTATUS_MASK;
7066 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
7067 break;
7068 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7069 if (!(_scsih_is_end_device(
7070 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7071 continue;
7072 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
7073 le64_to_cpu(sas_device_pg0.SASAddress));
7074 if (sas_device)
7075 continue;
7076 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7077 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7078 mpt2sas_transport_update_links(ioc, sas_address, handle,
7079 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7080 _scsih_add_device(ioc, handle, 0, 0);
7081 }
7082 }
7083
7084 printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307085}
7086
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307087
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307088/**
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307089 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
7090 * @ioc: per adapter object
7091 * @reset_phase: phase
7092 *
7093 * The handler for doing any required cleanup or initialization.
7094 *
7095 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
7096 * MPT2_IOC_DONE_RESET
7097 *
7098 * Return nothing.
7099 */
7100void
7101mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
7102{
7103 switch (reset_phase) {
7104 case MPT2_IOC_PRE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05307105 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307106 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307107 break;
7108 case MPT2_IOC_AFTER_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05307109 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307110 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307111 if (ioc->scsih_cmds.status & MPT2_CMD_PENDING) {
7112 ioc->scsih_cmds.status |= MPT2_CMD_RESET;
7113 mpt2sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
7114 complete(&ioc->scsih_cmds.done);
7115 }
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307116 if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
7117 ioc->tm_cmds.status |= MPT2_CMD_RESET;
7118 mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
7119 complete(&ioc->tm_cmds.done);
7120 }
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307121 _scsih_fw_event_cleanup_queue(ioc);
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307122 _scsih_flush_running_cmds(ioc);
7123 break;
7124 case MPT2_IOC_DONE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05307125 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307126 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307127 _scsih_sas_host_refresh(ioc);
Kashyap, Desai14695852010-03-30 10:52:44 +05307128 _scsih_prep_device_scan(ioc);
7129 _scsih_search_responding_sas_devices(ioc);
7130 _scsih_search_responding_raid_devices(ioc);
7131 _scsih_search_responding_expanders(ioc);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05307132 if (!ioc->is_driver_loading) {
7133 _scsih_prep_device_scan(ioc);
7134 _scsih_search_responding_sas_devices(ioc);
7135 _scsih_search_responding_raid_devices(ioc);
7136 _scsih_search_responding_expanders(ioc);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307137 _scsih_error_recovery_delete_devices(ioc);
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05307138 }
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05307139 break;
Eric Moore635374e2009-03-09 01:21:12 -06007140 }
7141}
7142
7143/**
7144 * _firmware_event_work - delayed task for processing firmware events
7145 * @ioc: per adapter object
7146 * @work: equal to the fw_event_work object
7147 * Context: user.
7148 *
7149 * Return nothing.
7150 */
7151static void
7152_firmware_event_work(struct work_struct *work)
7153{
7154 struct fw_event_work *fw_event = container_of(work,
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307155 struct fw_event_work, delayed_work.work);
Eric Moore635374e2009-03-09 01:21:12 -06007156 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
7157
Eric Moore635374e2009-03-09 01:21:12 -06007158 /* the queue is being flushed so ignore this event */
Eric Moore3cb54692010-07-08 14:44:34 -06007159 if (ioc->remove_host || fw_event->cancel_pending_work ||
7160 ioc->pci_error_recovery) {
Eric Moore635374e2009-03-09 01:21:12 -06007161 _scsih_fw_event_free(ioc, fw_event);
7162 return;
7163 }
Eric Moore635374e2009-03-09 01:21:12 -06007164
Eric Moore635374e2009-03-09 01:21:12 -06007165 switch (fw_event->event) {
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307166 case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
7167 while (scsi_host_in_recovery(ioc->shost))
7168 ssleep(1);
7169 _scsih_remove_unresponding_sas_devices(ioc);
7170 _scsih_scan_for_devices_after_reset(ioc);
7171 break;
7172 case MPT2SAS_PORT_ENABLE_COMPLETE:
nagalakshmi.nandigama@lsi.com918134e2011-10-19 15:37:24 +05307173 ioc->start_scan = 0;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307174
7175
7176
7177 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
7178 "from worker thread\n", ioc->name));
7179 break;
Kashyap, Desai3ace8e02011-05-04 16:35:58 +05307180 case MPT2SAS_TURN_ON_FAULT_LED:
7181 _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
7182 break;
Eric Moore635374e2009-03-09 01:21:12 -06007183 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307184 _scsih_sas_topology_change_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007185 break;
7186 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307187 _scsih_sas_device_status_change_event(ioc,
7188 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007189 break;
7190 case MPI2_EVENT_SAS_DISCOVERY:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307191 _scsih_sas_discovery_event(ioc,
7192 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007193 break;
7194 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307195 _scsih_sas_broadcast_primative_event(ioc,
7196 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007197 break;
7198 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7199 _scsih_sas_enclosure_dev_status_change_event(ioc,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307200 fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007201 break;
7202 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307203 _scsih_sas_ir_config_change_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007204 break;
7205 case MPI2_EVENT_IR_VOLUME:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307206 _scsih_sas_ir_volume_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007207 break;
7208 case MPI2_EVENT_IR_PHYSICAL_DISK:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307209 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007210 break;
7211 case MPI2_EVENT_IR_OPERATION_STATUS:
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307212 _scsih_sas_ir_operation_status_event(ioc, fw_event);
Eric Moore635374e2009-03-09 01:21:12 -06007213 break;
Eric Moore635374e2009-03-09 01:21:12 -06007214 }
7215 _scsih_fw_event_free(ioc, fw_event);
7216}
7217
7218/**
7219 * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
7220 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307221 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -06007222 * @reply: reply message frame(lower 32bit addr)
7223 * Context: interrupt.
7224 *
7225 * This function merely adds a new work task into ioc->firmware_event_thread.
7226 * The tasks are worked from _firmware_event_work in user context.
7227 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307228 * Return 1 meaning mf should be freed from _base_interrupt
7229 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -06007230 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307231u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307232mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
7233 u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -06007234{
7235 struct fw_event_work *fw_event;
7236 Mpi2EventNotificationReply_t *mpi_reply;
Eric Moore635374e2009-03-09 01:21:12 -06007237 u16 event;
Kashyap, Desaie94f6742010-03-17 16:24:52 +05307238 u16 sz;
Eric Moore635374e2009-03-09 01:21:12 -06007239
7240 /* events turned off due to host reset or driver unloading */
Eric Moore3cb54692010-07-08 14:44:34 -06007241 if (ioc->remove_host || ioc->pci_error_recovery)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307242 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007243
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307244 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
Eric Moore635374e2009-03-09 01:21:12 -06007245 event = le16_to_cpu(mpi_reply->Event);
7246
7247 switch (event) {
7248 /* handle these */
7249 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7250 {
7251 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7252 (Mpi2EventDataSasBroadcastPrimitive_t *)
7253 mpi_reply->EventData;
7254
7255 if (baen_data->Primitive !=
Kashyap, Desaif93213d2011-06-14 10:56:43 +05307256 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307257 return 1;
Kashyap, Desaif93213d2011-06-14 10:56:43 +05307258
7259 if (ioc->broadcast_aen_busy) {
7260 ioc->broadcast_aen_pending++;
7261 return 1;
7262 } else
7263 ioc->broadcast_aen_busy = 1;
Eric Moore635374e2009-03-09 01:21:12 -06007264 break;
7265 }
7266
7267 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7268 _scsih_check_topo_delete_events(ioc,
7269 (Mpi2EventDataSasTopologyChangeList_t *)
7270 mpi_reply->EventData);
7271 break;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05307272 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7273 _scsih_check_ir_config_unhide_events(ioc,
7274 (Mpi2EventDataIrConfigChangeList_t *)
7275 mpi_reply->EventData);
7276 break;
7277 case MPI2_EVENT_IR_VOLUME:
7278 _scsih_check_volume_delete_events(ioc,
7279 (Mpi2EventDataIrVolume_t *)
7280 mpi_reply->EventData);
7281 break;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307282 case MPI2_EVENT_LOG_ENTRY_ADDED:
7283 {
7284 Mpi2EventDataLogEntryAdded_t *log_entry;
7285 u32 *log_code;
7286
7287 if (!ioc->is_warpdrive)
7288 break;
7289
7290 log_entry = (Mpi2EventDataLogEntryAdded_t *)
7291 mpi_reply->EventData;
7292 log_code = (u32 *)log_entry->LogData;
7293
7294 if (le16_to_cpu(log_entry->LogEntryQualifier)
7295 != MPT2_WARPDRIVE_LOGENTRY)
7296 break;
7297
7298 switch (le32_to_cpu(*log_code)) {
7299 case MPT2_WARPDRIVE_LC_SSDT:
7300 printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
7301 "IO Throttling has occurred in the WarpDrive "
7302 "subsystem. Check WarpDrive documentation for "
7303 "additional details.\n", ioc->name);
7304 break;
7305 case MPT2_WARPDRIVE_LC_SSDLW:
7306 printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
7307 "Program/Erase Cycles for the WarpDrive subsystem "
7308 "in degraded range. Check WarpDrive documentation "
7309 "for additional details.\n", ioc->name);
7310 break;
7311 case MPT2_WARPDRIVE_LC_SSDLF:
7312 printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
7313 "There are no Program/Erase Cycles for the "
7314 "WarpDrive subsystem. The storage device will be "
7315 "in read-only mode. Check WarpDrive documentation "
7316 "for additional details.\n", ioc->name);
7317 break;
7318 case MPT2_WARPDRIVE_LC_BRMF:
7319 printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
7320 "The Backup Rail Monitor has failed on the "
7321 "WarpDrive subsystem. Check WarpDrive "
7322 "documentation for additional details.\n",
7323 ioc->name);
7324 break;
7325 }
7326
7327 break;
7328 }
Eric Moore635374e2009-03-09 01:21:12 -06007329 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7330 case MPI2_EVENT_IR_OPERATION_STATUS:
7331 case MPI2_EVENT_SAS_DISCOVERY:
7332 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
Eric Moore635374e2009-03-09 01:21:12 -06007333 case MPI2_EVENT_IR_PHYSICAL_DISK:
Eric Moore635374e2009-03-09 01:21:12 -06007334 break;
7335
7336 default: /* ignore the rest */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307337 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007338 }
7339
7340 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
7341 if (!fw_event) {
7342 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7343 ioc->name, __FILE__, __LINE__, __func__);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307344 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007345 }
Kashyap, Desaie94f6742010-03-17 16:24:52 +05307346 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
7347 fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
Eric Moore635374e2009-03-09 01:21:12 -06007348 if (!fw_event->event_data) {
7349 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7350 ioc->name, __FILE__, __LINE__, __func__);
7351 kfree(fw_event);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307352 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007353 }
7354
7355 memcpy(fw_event->event_data, mpi_reply->EventData,
Kashyap, Desaie94f6742010-03-17 16:24:52 +05307356 sz);
Eric Moore635374e2009-03-09 01:21:12 -06007357 fw_event->ioc = ioc;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05307358 fw_event->VF_ID = mpi_reply->VF_ID;
7359 fw_event->VP_ID = mpi_reply->VP_ID;
Eric Moore635374e2009-03-09 01:21:12 -06007360 fw_event->event = event;
7361 _scsih_fw_event_add(ioc, fw_event);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307362 return 1;
Eric Moore635374e2009-03-09 01:21:12 -06007363}
7364
7365/* shost template */
7366static struct scsi_host_template scsih_driver_template = {
7367 .module = THIS_MODULE,
7368 .name = "Fusion MPT SAS Host",
7369 .proc_name = MPT2SAS_DRIVER_NAME,
Eric Moored5d135b2009-05-18 13:02:08 -06007370 .queuecommand = _scsih_qcmd,
7371 .target_alloc = _scsih_target_alloc,
7372 .slave_alloc = _scsih_slave_alloc,
7373 .slave_configure = _scsih_slave_configure,
7374 .target_destroy = _scsih_target_destroy,
7375 .slave_destroy = _scsih_slave_destroy,
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307376 .scan_finished = _scsih_scan_finished,
7377 .scan_start = _scsih_scan_start,
Eric Moored5d135b2009-05-18 13:02:08 -06007378 .change_queue_depth = _scsih_change_queue_depth,
7379 .change_queue_type = _scsih_change_queue_type,
7380 .eh_abort_handler = _scsih_abort,
7381 .eh_device_reset_handler = _scsih_dev_reset,
7382 .eh_target_reset_handler = _scsih_target_reset,
7383 .eh_host_reset_handler = _scsih_host_reset,
7384 .bios_param = _scsih_bios_param,
Eric Moore635374e2009-03-09 01:21:12 -06007385 .can_queue = 1,
7386 .this_id = -1,
7387 .sg_tablesize = MPT2SAS_SG_DEPTH,
7388 .max_sectors = 8192,
7389 .cmd_per_lun = 7,
7390 .use_clustering = ENABLE_CLUSTERING,
7391 .shost_attrs = mpt2sas_host_attrs,
7392 .sdev_attrs = mpt2sas_dev_attrs,
7393};
7394
7395/**
7396 * _scsih_expander_node_remove - removing expander device from list.
7397 * @ioc: per adapter object
7398 * @sas_expander: the sas_device object
7399 * Context: Calling function should acquire ioc->sas_node_lock.
7400 *
7401 * Removing object and freeing associated memory from the
7402 * ioc->sas_expander_list.
7403 *
7404 * Return nothing.
7405 */
7406static void
7407_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
7408 struct _sas_node *sas_expander)
7409{
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307410 struct _sas_port *mpt2sas_port, *next;
Eric Moore635374e2009-03-09 01:21:12 -06007411
7412 /* remove sibling ports attached to this expander */
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307413 list_for_each_entry_safe(mpt2sas_port, next,
Eric Moore635374e2009-03-09 01:21:12 -06007414 &sas_expander->sas_port_list, port_list) {
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307415 if (ioc->shost_recovery)
7416 return;
Eric Moore635374e2009-03-09 01:21:12 -06007417 if (mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307418 SAS_END_DEVICE)
7419 mpt2sas_device_remove(ioc,
7420 mpt2sas_port->remote_identify.sas_address);
7421 else if (mpt2sas_port->remote_identify.device_type ==
7422 SAS_EDGE_EXPANDER_DEVICE ||
Eric Moore635374e2009-03-09 01:21:12 -06007423 mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307424 SAS_FANOUT_EXPANDER_DEVICE)
7425 mpt2sas_expander_remove(ioc,
7426 mpt2sas_port->remote_identify.sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06007427 }
7428
7429 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307430 sas_expander->sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06007431
7432 printk(MPT2SAS_INFO_FMT "expander_remove: handle"
7433 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7434 sas_expander->handle, (unsigned long long)
7435 sas_expander->sas_address);
7436
Eric Moore635374e2009-03-09 01:21:12 -06007437 kfree(sas_expander->phy);
7438 kfree(sas_expander);
7439}
7440
7441/**
Kashyap, Desai744090d2009-10-05 15:56:56 +05307442 * _scsih_ir_shutdown - IR shutdown notification
7443 * @ioc: per adapter object
7444 *
7445 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
7446 * the host system is shutting down.
7447 *
7448 * Return nothing.
7449 */
7450static void
7451_scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
7452{
7453 Mpi2RaidActionRequest_t *mpi_request;
7454 Mpi2RaidActionReply_t *mpi_reply;
7455 u16 smid;
7456
7457 /* is IR firmware build loaded ? */
7458 if (!ioc->ir_firmware)
7459 return;
7460
7461 /* are there any volumes ? */
7462 if (list_empty(&ioc->raid_device_list))
7463 return;
7464
7465 mutex_lock(&ioc->scsih_cmds.mutex);
7466
7467 if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) {
7468 printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n",
7469 ioc->name, __func__);
7470 goto out;
7471 }
7472 ioc->scsih_cmds.status = MPT2_CMD_PENDING;
7473
7474 smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx);
7475 if (!smid) {
7476 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
7477 ioc->name, __func__);
7478 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
7479 goto out;
7480 }
7481
7482 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
7483 ioc->scsih_cmds.smid = smid;
7484 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
7485
7486 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
7487 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
7488
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307489 if (!ioc->hide_ir_msg)
7490 printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
Kashyap, Desai744090d2009-10-05 15:56:56 +05307491 init_completion(&ioc->scsih_cmds.done);
7492 mpt2sas_base_put_smid_default(ioc, smid);
7493 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
7494
7495 if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) {
7496 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
7497 ioc->name, __func__);
7498 goto out;
7499 }
7500
7501 if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
7502 mpi_reply = ioc->scsih_cmds.reply;
7503
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307504 if (!ioc->hide_ir_msg)
7505 printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
7506 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7507 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
7508 le32_to_cpu(mpi_reply->IOCLogInfo));
Kashyap, Desai744090d2009-10-05 15:56:56 +05307509 }
7510
7511 out:
7512 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
7513 mutex_unlock(&ioc->scsih_cmds.mutex);
7514}
7515
7516/**
7517 * _scsih_shutdown - routine call during system shutdown
7518 * @pdev: PCI device struct
7519 *
7520 * Return nothing.
7521 */
7522static void
7523_scsih_shutdown(struct pci_dev *pdev)
7524{
7525 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7526 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307527 struct workqueue_struct *wq;
7528 unsigned long flags;
7529
7530 ioc->remove_host = 1;
7531 _scsih_fw_event_cleanup_queue(ioc);
7532
7533 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7534 wq = ioc->firmware_event_thread;
7535 ioc->firmware_event_thread = NULL;
7536 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7537 if (wq)
7538 destroy_workqueue(wq);
Kashyap, Desai744090d2009-10-05 15:56:56 +05307539
7540 _scsih_ir_shutdown(ioc);
7541 mpt2sas_base_detach(ioc);
7542}
7543
7544/**
Eric Moored5d135b2009-05-18 13:02:08 -06007545 * _scsih_remove - detach and remove add host
Eric Moore635374e2009-03-09 01:21:12 -06007546 * @pdev: PCI device struct
7547 *
Kashyap, Desai744090d2009-10-05 15:56:56 +05307548 * Routine called when unloading the driver.
Eric Moore635374e2009-03-09 01:21:12 -06007549 * Return nothing.
7550 */
7551static void __devexit
Eric Moored5d135b2009-05-18 13:02:08 -06007552_scsih_remove(struct pci_dev *pdev)
Eric Moore635374e2009-03-09 01:21:12 -06007553{
7554 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7555 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307556 struct _sas_port *mpt2sas_port, *next_port;
Kashyap, Desaid7384b22009-12-16 18:50:06 +05307557 struct _raid_device *raid_device, *next;
7558 struct MPT2SAS_TARGET *sas_target_priv_data;
Eric Moore635374e2009-03-09 01:21:12 -06007559 struct workqueue_struct *wq;
7560 unsigned long flags;
7561
7562 ioc->remove_host = 1;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05307563 _scsih_fw_event_cleanup_queue(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007564
7565 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7566 wq = ioc->firmware_event_thread;
7567 ioc->firmware_event_thread = NULL;
7568 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7569 if (wq)
7570 destroy_workqueue(wq);
7571
Kashyap, Desaid7384b22009-12-16 18:50:06 +05307572 /* release all the volumes */
Kashyap, Desai3a9c9132011-01-04 11:40:23 +05307573 _scsih_ir_shutdown(ioc);
Kashyap, Desaid7384b22009-12-16 18:50:06 +05307574 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
7575 list) {
7576 if (raid_device->starget) {
7577 sas_target_priv_data =
7578 raid_device->starget->hostdata;
7579 sas_target_priv_data->deleted = 1;
7580 scsi_remove_target(&raid_device->starget->dev);
7581 }
7582 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
7583 "(0x%016llx)\n", ioc->name, raid_device->handle,
7584 (unsigned long long) raid_device->wwid);
7585 _scsih_raid_device_remove(ioc, raid_device);
7586 }
7587
Eric Moore635374e2009-03-09 01:21:12 -06007588 /* free ports attached to the sas_host */
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307589 list_for_each_entry_safe(mpt2sas_port, next_port,
Eric Moore635374e2009-03-09 01:21:12 -06007590 &ioc->sas_hba.sas_port_list, port_list) {
7591 if (mpt2sas_port->remote_identify.device_type ==
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307592 SAS_END_DEVICE)
7593 mpt2sas_device_remove(ioc,
Eric Moore635374e2009-03-09 01:21:12 -06007594 mpt2sas_port->remote_identify.sas_address);
Kashyap, Desai7f6f7942010-11-13 04:35:30 +05307595 else if (mpt2sas_port->remote_identify.device_type ==
7596 SAS_EDGE_EXPANDER_DEVICE ||
7597 mpt2sas_port->remote_identify.device_type ==
7598 SAS_FANOUT_EXPANDER_DEVICE)
7599 mpt2sas_expander_remove(ioc,
7600 mpt2sas_port->remote_identify.sas_address);
Eric Moore635374e2009-03-09 01:21:12 -06007601 }
7602
7603 /* free phys attached to the sas_host */
7604 if (ioc->sas_hba.num_phys) {
7605 kfree(ioc->sas_hba.phy);
7606 ioc->sas_hba.phy = NULL;
7607 ioc->sas_hba.num_phys = 0;
7608 }
7609
7610 sas_remove_host(shost);
kashyap.desai@lsi.com9ae89b02011-08-04 16:47:50 +05307611 mpt2sas_base_detach(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007612 list_del(&ioc->list);
7613 scsi_remove_host(shost);
7614 scsi_host_put(shost);
7615}
7616
7617/**
7618 * _scsih_probe_boot_devices - reports 1st device
7619 * @ioc: per adapter object
7620 *
7621 * If specified in bios page 2, this routine reports the 1st
7622 * device scsi-ml or sas transport for persistent boot device
7623 * purposes. Please refer to function _scsih_determine_boot_device()
7624 */
7625static void
7626_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
7627{
7628 u8 is_raid;
7629 void *device;
7630 struct _sas_device *sas_device;
7631 struct _raid_device *raid_device;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307632 u16 handle;
7633 u64 sas_address_parent;
Eric Moore635374e2009-03-09 01:21:12 -06007634 u64 sas_address;
7635 unsigned long flags;
7636 int rc;
7637
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307638 /* no Bios, return immediately */
7639 if (!ioc->bios_pg3.BiosVersion)
7640 return;
7641
Eric Moore635374e2009-03-09 01:21:12 -06007642 device = NULL;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307643 is_raid = 0;
Eric Moore635374e2009-03-09 01:21:12 -06007644 if (ioc->req_boot_device.device) {
7645 device = ioc->req_boot_device.device;
7646 is_raid = ioc->req_boot_device.is_raid;
7647 } else if (ioc->req_alt_boot_device.device) {
7648 device = ioc->req_alt_boot_device.device;
7649 is_raid = ioc->req_alt_boot_device.is_raid;
7650 } else if (ioc->current_boot_device.device) {
7651 device = ioc->current_boot_device.device;
7652 is_raid = ioc->current_boot_device.is_raid;
7653 }
7654
7655 if (!device)
7656 return;
7657
7658 if (is_raid) {
7659 raid_device = device;
7660 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
7661 raid_device->id, 0);
7662 if (rc)
7663 _scsih_raid_device_remove(ioc, raid_device);
7664 } else {
7665 sas_device = device;
7666 handle = sas_device->handle;
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307667 sas_address_parent = sas_device->sas_address_parent;
Eric Moore635374e2009-03-09 01:21:12 -06007668 sas_address = sas_device->sas_address;
7669 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7670 list_move_tail(&sas_device->list, &ioc->sas_device_list);
7671 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307672
7673 if (ioc->hide_drives)
7674 return;
Eric Moore635374e2009-03-09 01:21:12 -06007675 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307676 sas_device->sas_address_parent)) {
Eric Moore635374e2009-03-09 01:21:12 -06007677 _scsih_sas_device_remove(ioc, sas_device);
7678 } else if (!sas_device->starget) {
7679 mpt2sas_transport_port_remove(ioc, sas_address,
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307680 sas_address_parent);
Eric Moore635374e2009-03-09 01:21:12 -06007681 _scsih_sas_device_remove(ioc, sas_device);
7682 }
7683 }
7684}
7685
7686/**
7687 * _scsih_probe_raid - reporting raid volumes to scsi-ml
7688 * @ioc: per adapter object
7689 *
7690 * Called during initial loading of the driver.
7691 */
7692static void
7693_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
7694{
7695 struct _raid_device *raid_device, *raid_next;
7696 int rc;
7697
7698 list_for_each_entry_safe(raid_device, raid_next,
7699 &ioc->raid_device_list, list) {
7700 if (raid_device->starget)
7701 continue;
7702 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
7703 raid_device->id, 0);
7704 if (rc)
7705 _scsih_raid_device_remove(ioc, raid_device);
7706 }
7707}
7708
7709/**
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307710 * _scsih_probe_sas - reporting sas devices to sas transport
Eric Moore635374e2009-03-09 01:21:12 -06007711 * @ioc: per adapter object
7712 *
7713 * Called during initial loading of the driver.
7714 */
7715static void
7716_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
7717{
7718 struct _sas_device *sas_device, *next;
7719 unsigned long flags;
Eric Moore635374e2009-03-09 01:21:12 -06007720
7721 /* SAS Device List */
7722 list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
7723 list) {
Eric Moore635374e2009-03-09 01:21:12 -06007724
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307725 if (ioc->hide_drives)
7726 continue;
7727
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307728 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
7729 sas_device->sas_address_parent)) {
nagalakshmi.nandigama@lsi.com0167ac62011-10-21 10:06:33 +05307730 list_del(&sas_device->list);
7731 kfree(sas_device);
7732 continue;
Eric Moore635374e2009-03-09 01:21:12 -06007733 } else if (!sas_device->starget) {
Kashyap, Desaic5e039b2009-09-23 17:21:29 +05307734 mpt2sas_transport_port_remove(ioc,
7735 sas_device->sas_address,
7736 sas_device->sas_address_parent);
nagalakshmi.nandigama@lsi.com0167ac62011-10-21 10:06:33 +05307737 list_del(&sas_device->list);
7738 kfree(sas_device);
7739 continue;
7740
Eric Moore635374e2009-03-09 01:21:12 -06007741 }
nagalakshmi.nandigama@lsi.com0167ac62011-10-21 10:06:33 +05307742 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7743 list_move_tail(&sas_device->list, &ioc->sas_device_list);
7744 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06007745 }
7746}
7747
7748/**
7749 * _scsih_probe_devices - probing for devices
7750 * @ioc: per adapter object
7751 *
7752 * Called during initial loading of the driver.
7753 */
7754static void
7755_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
7756{
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307757 u16 volume_mapping_flags;
Eric Moore635374e2009-03-09 01:21:12 -06007758
7759 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
7760 return; /* return when IOC doesn't support initiator mode */
7761
7762 _scsih_probe_boot_devices(ioc);
7763
7764 if (ioc->ir_firmware) {
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307765 volume_mapping_flags =
7766 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
7767 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
7768 if (volume_mapping_flags ==
7769 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
Eric Moore635374e2009-03-09 01:21:12 -06007770 _scsih_probe_raid(ioc);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307771 _scsih_probe_sas(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007772 } else {
Eric Moore635374e2009-03-09 01:21:12 -06007773 _scsih_probe_sas(ioc);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307774 _scsih_probe_raid(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06007775 }
7776 } else
7777 _scsih_probe_sas(ioc);
7778}
7779
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307780
7781/**
7782 * _scsih_scan_start - scsi lld callback for .scan_start
7783 * @shost: SCSI host pointer
7784 *
7785 * The shost has the ability to discover targets on its own instead
7786 * of scanning the entire bus. In our implemention, we will kick off
7787 * firmware discovery.
7788 */
7789static void
7790_scsih_scan_start(struct Scsi_Host *shost)
7791{
7792 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
7793 int rc;
7794
7795 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
7796 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
7797
7798 ioc->start_scan = 1;
7799 rc = mpt2sas_port_enable(ioc);
7800
7801 if (rc != 0)
7802 printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
7803}
7804
7805/**
7806 * _scsih_scan_finished - scsi lld callback for .scan_finished
7807 * @shost: SCSI host pointer
7808 * @time: elapsed time of the scan in jiffies
7809 *
7810 * This function will be called periodically until it returns 1 with the
7811 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
7812 * we wait for firmware discovery to complete, then return 1.
7813 */
7814static int
7815_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
7816{
7817 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
7818
7819 if (time >= (300 * HZ)) {
7820 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
7821 printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
7822 "(timeout=300s)\n", ioc->name);
7823 ioc->is_driver_loading = 0;
7824 return 1;
7825 }
7826
7827 if (ioc->start_scan)
7828 return 0;
7829
7830 if (ioc->start_scan_failed) {
7831 printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
7832 "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
7833 ioc->is_driver_loading = 0;
7834 ioc->wait_for_discovery_to_complete = 0;
7835 ioc->remove_host = 1;
7836 return 1;
7837 }
7838
7839 printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
7840 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
7841
7842 if (ioc->wait_for_discovery_to_complete) {
7843 ioc->wait_for_discovery_to_complete = 0;
7844 _scsih_probe_devices(ioc);
7845 }
7846 mpt2sas_base_start_watchdog(ioc);
7847 ioc->is_driver_loading = 0;
7848 return 1;
7849}
7850
7851
Eric Moore635374e2009-03-09 01:21:12 -06007852/**
Eric Moored5d135b2009-05-18 13:02:08 -06007853 * _scsih_probe - attach and add scsi host
Eric Moore635374e2009-03-09 01:21:12 -06007854 * @pdev: PCI device struct
7855 * @id: pci device id
7856 *
7857 * Returns 0 success, anything else error.
7858 */
7859static int
Eric Moored5d135b2009-05-18 13:02:08 -06007860_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
Eric Moore635374e2009-03-09 01:21:12 -06007861{
7862 struct MPT2SAS_ADAPTER *ioc;
7863 struct Scsi_Host *shost;
7864
7865 shost = scsi_host_alloc(&scsih_driver_template,
7866 sizeof(struct MPT2SAS_ADAPTER));
7867 if (!shost)
7868 return -ENODEV;
7869
7870 /* init local params */
7871 ioc = shost_priv(shost);
7872 memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER));
7873 INIT_LIST_HEAD(&ioc->list);
Eric Mooreba33fad2009-03-15 21:37:18 -06007874 list_add_tail(&ioc->list, &mpt2sas_ioc_list);
Eric Moore635374e2009-03-09 01:21:12 -06007875 ioc->shost = shost;
7876 ioc->id = mpt_ids++;
7877 sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
7878 ioc->pdev = pdev;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307879 if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) {
7880 ioc->is_warpdrive = 1;
7881 ioc->hide_ir_msg = 1;
7882 } else
7883 ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
Eric Moore635374e2009-03-09 01:21:12 -06007884 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
7885 ioc->tm_cb_idx = tm_cb_idx;
7886 ioc->ctl_cb_idx = ctl_cb_idx;
7887 ioc->base_cb_idx = base_cb_idx;
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307888 ioc->port_enable_cb_idx = port_enable_cb_idx;
Eric Moore635374e2009-03-09 01:21:12 -06007889 ioc->transport_cb_idx = transport_cb_idx;
Kashyap, Desai744090d2009-10-05 15:56:56 +05307890 ioc->scsih_cb_idx = scsih_cb_idx;
Eric Moore635374e2009-03-09 01:21:12 -06007891 ioc->config_cb_idx = config_cb_idx;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307892 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05307893 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307894 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
Eric Moore635374e2009-03-09 01:21:12 -06007895 ioc->logging_level = logging_level;
7896 /* misc semaphores and spin locks */
Kashyap, Desaid2742132010-06-17 13:28:55 +05307897 mutex_init(&ioc->reset_in_progress_mutex);
Eric Moore635374e2009-03-09 01:21:12 -06007898 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
7899 spin_lock_init(&ioc->scsi_lookup_lock);
7900 spin_lock_init(&ioc->sas_device_lock);
7901 spin_lock_init(&ioc->sas_node_lock);
7902 spin_lock_init(&ioc->fw_event_lock);
7903 spin_lock_init(&ioc->raid_device_lock);
7904
7905 INIT_LIST_HEAD(&ioc->sas_device_list);
7906 INIT_LIST_HEAD(&ioc->sas_device_init_list);
7907 INIT_LIST_HEAD(&ioc->sas_expander_list);
7908 INIT_LIST_HEAD(&ioc->fw_event_list);
7909 INIT_LIST_HEAD(&ioc->raid_device_list);
7910 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307911 INIT_LIST_HEAD(&ioc->delayed_tr_list);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05307912 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
Eric Moore635374e2009-03-09 01:21:12 -06007913
7914 /* init shost parameters */
Eric Moored334aa72010-04-22 10:47:40 -06007915 shost->max_cmd_len = 32;
Eric Moore635374e2009-03-09 01:21:12 -06007916 shost->max_lun = max_lun;
7917 shost->transportt = mpt2sas_transport_template;
7918 shost->unique_id = ioc->id;
7919
Kashyap, Desaia3e1e552011-06-14 10:56:12 +05307920 if (max_sectors != 0xFFFF) {
7921 if (max_sectors < 64) {
7922 shost->max_sectors = 64;
7923 printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
7924 "for max_sectors, range is 64 to 8192. Assigning "
7925 "value of 64.\n", ioc->name, max_sectors);
7926 } else if (max_sectors > 8192) {
7927 shost->max_sectors = 8192;
7928 printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
7929 "for max_sectors, range is 64 to 8192. Assigning "
7930 "default value of 8192.\n", ioc->name,
7931 max_sectors);
7932 } else {
7933 shost->max_sectors = max_sectors & 0xFFFE;
7934 printk(MPT2SAS_INFO_FMT "The max_sectors value is "
7935 "set to %d\n", ioc->name, shost->max_sectors);
7936 }
7937 }
7938
Eric Moore635374e2009-03-09 01:21:12 -06007939 if ((scsi_add_host(shost, &pdev->dev))) {
7940 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7941 ioc->name, __FILE__, __LINE__, __func__);
7942 list_del(&ioc->list);
7943 goto out_add_shost_fail;
7944 }
7945
Eric Moore3c621b32009-05-18 12:59:41 -06007946 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
Eric Moored334aa72010-04-22 10:47:40 -06007947 | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05307948 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
Eric Moore3c621b32009-05-18 12:59:41 -06007949
Eric Moore635374e2009-03-09 01:21:12 -06007950 /* event thread */
7951 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
7952 "fw_event%d", ioc->id);
7953 ioc->firmware_event_thread = create_singlethread_workqueue(
7954 ioc->firmware_event_name);
7955 if (!ioc->firmware_event_thread) {
7956 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7957 ioc->name, __FILE__, __LINE__, __func__);
7958 goto out_thread_fail;
7959 }
7960
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307961 ioc->is_driver_loading = 1;
Eric Moore635374e2009-03-09 01:21:12 -06007962 if ((mpt2sas_base_attach(ioc))) {
7963 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7964 ioc->name, __FILE__, __LINE__, __func__);
7965 goto out_attach_fail;
7966 }
7967
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307968 scsi_scan_host(shost);
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05307969 if (ioc->is_warpdrive) {
7970 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
7971 ioc->hide_drives = 0;
7972 else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
7973 ioc->hide_drives = 1;
7974 else {
7975 if (_scsih_get_num_volumes(ioc))
7976 ioc->hide_drives = 1;
7977 else
7978 ioc->hide_drives = 0;
7979 }
7980 } else
7981 ioc->hide_drives = 0;
7982
Eric Moore635374e2009-03-09 01:21:12 -06007983 _scsih_probe_devices(ioc);
7984 return 0;
7985
7986 out_attach_fail:
7987 destroy_workqueue(ioc->firmware_event_thread);
7988 out_thread_fail:
7989 list_del(&ioc->list);
7990 scsi_remove_host(shost);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05307991 scsi_host_put(shost);
Eric Moore635374e2009-03-09 01:21:12 -06007992 out_add_shost_fail:
7993 return -ENODEV;
7994}
7995
7996#ifdef CONFIG_PM
7997/**
Eric Moored5d135b2009-05-18 13:02:08 -06007998 * _scsih_suspend - power management suspend main entry point
Eric Moore635374e2009-03-09 01:21:12 -06007999 * @pdev: PCI device struct
8000 * @state: PM state change to (usually PCI_D3)
8001 *
8002 * Returns 0 success, anything else error.
8003 */
8004static int
Eric Moored5d135b2009-05-18 13:02:08 -06008005_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
Eric Moore635374e2009-03-09 01:21:12 -06008006{
8007 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8008 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desaic97951e2011-06-14 10:54:56 +05308009 pci_power_t device_state;
Eric Moore635374e2009-03-09 01:21:12 -06008010
Kashyap, Desaie4750c92009-08-07 19:37:59 +05308011 mpt2sas_base_stop_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06008012 scsi_block_requests(shost);
8013 device_state = pci_choose_state(pdev, state);
8014 printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
8015 "operating state [D%d]\n", ioc->name, pdev,
8016 pci_name(pdev), device_state);
8017
8018 mpt2sas_base_free_resources(ioc);
8019 pci_save_state(pdev);
8020 pci_disable_device(pdev);
8021 pci_set_power_state(pdev, device_state);
8022 return 0;
8023}
8024
8025/**
Eric Moored5d135b2009-05-18 13:02:08 -06008026 * _scsih_resume - power management resume main entry point
Eric Moore635374e2009-03-09 01:21:12 -06008027 * @pdev: PCI device struct
8028 *
8029 * Returns 0 success, anything else error.
8030 */
8031static int
Eric Moored5d135b2009-05-18 13:02:08 -06008032_scsih_resume(struct pci_dev *pdev)
Eric Moore635374e2009-03-09 01:21:12 -06008033{
8034 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8035 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Kashyap, Desaic97951e2011-06-14 10:54:56 +05308036 pci_power_t device_state = pdev->current_state;
Eric Moore635374e2009-03-09 01:21:12 -06008037 int r;
8038
8039 printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
8040 "operating state [D%d]\n", ioc->name, pdev,
8041 pci_name(pdev), device_state);
8042
8043 pci_set_power_state(pdev, PCI_D0);
8044 pci_enable_wake(pdev, PCI_D0, 0);
8045 pci_restore_state(pdev);
8046 ioc->pdev = pdev;
8047 r = mpt2sas_base_map_resources(ioc);
8048 if (r)
8049 return r;
8050
8051 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
8052 scsi_unblock_requests(shost);
Kashyap, Desaie4750c92009-08-07 19:37:59 +05308053 mpt2sas_base_start_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06008054 return 0;
8055}
8056#endif /* CONFIG_PM */
8057
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308058/**
8059 * _scsih_pci_error_detected - Called when a PCI error is detected.
8060 * @pdev: PCI device struct
8061 * @state: PCI channel state
8062 *
8063 * Description: Called when a PCI error is detected.
8064 *
8065 * Return value:
8066 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
8067 */
8068static pci_ers_result_t
8069_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
8070{
8071 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8072 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8073
8074 printk(MPT2SAS_INFO_FMT "PCI error: detected callback, state(%d)!!\n",
8075 ioc->name, state);
8076
8077 switch (state) {
8078 case pci_channel_io_normal:
8079 return PCI_ERS_RESULT_CAN_RECOVER;
8080 case pci_channel_io_frozen:
Eric Moore3cb54692010-07-08 14:44:34 -06008081 /* Fatal error, prepare for slot reset */
8082 ioc->pci_error_recovery = 1;
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308083 scsi_block_requests(ioc->shost);
8084 mpt2sas_base_stop_watchdog(ioc);
8085 mpt2sas_base_free_resources(ioc);
8086 return PCI_ERS_RESULT_NEED_RESET;
8087 case pci_channel_io_perm_failure:
Eric Moore3cb54692010-07-08 14:44:34 -06008088 /* Permanent error, prepare for device removal */
8089 ioc->pci_error_recovery = 1;
8090 mpt2sas_base_stop_watchdog(ioc);
8091 _scsih_flush_running_cmds(ioc);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308092 return PCI_ERS_RESULT_DISCONNECT;
8093 }
8094 return PCI_ERS_RESULT_NEED_RESET;
8095}
8096
8097/**
8098 * _scsih_pci_slot_reset - Called when PCI slot has been reset.
8099 * @pdev: PCI device struct
8100 *
8101 * Description: This routine is called by the pci error recovery
8102 * code after the PCI slot has been reset, just before we
8103 * should resume normal operations.
8104 */
8105static pci_ers_result_t
8106_scsih_pci_slot_reset(struct pci_dev *pdev)
8107{
8108 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8109 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8110 int rc;
8111
8112 printk(MPT2SAS_INFO_FMT "PCI error: slot reset callback!!\n",
8113 ioc->name);
8114
Eric Moore3cb54692010-07-08 14:44:34 -06008115 ioc->pci_error_recovery = 0;
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308116 ioc->pdev = pdev;
Eric Moore3cb54692010-07-08 14:44:34 -06008117 pci_restore_state(pdev);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308118 rc = mpt2sas_base_map_resources(ioc);
8119 if (rc)
8120 return PCI_ERS_RESULT_DISCONNECT;
8121
8122
8123 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
8124 FORCE_BIG_HAMMER);
8125
8126 printk(MPT2SAS_WARN_FMT "hard reset: %s\n", ioc->name,
8127 (rc == 0) ? "success" : "failed");
8128
8129 if (!rc)
8130 return PCI_ERS_RESULT_RECOVERED;
8131 else
8132 return PCI_ERS_RESULT_DISCONNECT;
8133}
8134
8135/**
8136 * _scsih_pci_resume() - resume normal ops after PCI reset
8137 * @pdev: pointer to PCI device
8138 *
8139 * Called when the error recovery driver tells us that its
8140 * OK to resume normal operation. Use completion to allow
8141 * halted scsi ops to resume.
8142 */
8143static void
8144_scsih_pci_resume(struct pci_dev *pdev)
8145{
8146 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8147 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8148
8149 printk(MPT2SAS_INFO_FMT "PCI error: resume callback!!\n", ioc->name);
8150
8151 pci_cleanup_aer_uncorrect_error_status(pdev);
8152 mpt2sas_base_start_watchdog(ioc);
8153 scsi_unblock_requests(ioc->shost);
8154}
8155
8156/**
8157 * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
8158 * @pdev: pointer to PCI device
8159 */
8160static pci_ers_result_t
8161_scsih_pci_mmio_enabled(struct pci_dev *pdev)
8162{
8163 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8164 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
8165
8166 printk(MPT2SAS_INFO_FMT "PCI error: mmio enabled callback!!\n",
8167 ioc->name);
8168
8169 /* TODO - dump whatever for debugging purposes */
8170
8171 /* Request a slot reset. */
8172 return PCI_ERS_RESULT_NEED_RESET;
8173}
8174
8175static struct pci_error_handlers _scsih_err_handler = {
8176 .error_detected = _scsih_pci_error_detected,
8177 .mmio_enabled = _scsih_pci_mmio_enabled,
8178 .slot_reset = _scsih_pci_slot_reset,
8179 .resume = _scsih_pci_resume,
8180};
Eric Moore635374e2009-03-09 01:21:12 -06008181
8182static struct pci_driver scsih_driver = {
8183 .name = MPT2SAS_DRIVER_NAME,
8184 .id_table = scsih_pci_table,
Eric Moored5d135b2009-05-18 13:02:08 -06008185 .probe = _scsih_probe,
8186 .remove = __devexit_p(_scsih_remove),
Kashyap, Desai744090d2009-10-05 15:56:56 +05308187 .shutdown = _scsih_shutdown,
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05308188 .err_handler = &_scsih_err_handler,
Eric Moore635374e2009-03-09 01:21:12 -06008189#ifdef CONFIG_PM
Eric Moored5d135b2009-05-18 13:02:08 -06008190 .suspend = _scsih_suspend,
8191 .resume = _scsih_resume,
Eric Moore635374e2009-03-09 01:21:12 -06008192#endif
8193};
8194
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308195/* raid transport support */
8196static struct raid_function_template mpt2sas_raid_functions = {
8197 .cookie = &scsih_driver_template,
8198 .is_raid = _scsih_is_raid,
8199 .get_resync = _scsih_get_resync,
8200 .get_state = _scsih_get_state,
8201};
Eric Moore635374e2009-03-09 01:21:12 -06008202
8203/**
Eric Moored5d135b2009-05-18 13:02:08 -06008204 * _scsih_init - main entry point for this driver.
Eric Moore635374e2009-03-09 01:21:12 -06008205 *
8206 * Returns 0 success, anything else error.
8207 */
8208static int __init
Eric Moored5d135b2009-05-18 13:02:08 -06008209_scsih_init(void)
Eric Moore635374e2009-03-09 01:21:12 -06008210{
8211 int error;
8212
8213 mpt_ids = 0;
8214 printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
8215 MPT2SAS_DRIVER_VERSION);
8216
8217 mpt2sas_transport_template =
8218 sas_attach_transport(&mpt2sas_transport_functions);
8219 if (!mpt2sas_transport_template)
8220 return -ENODEV;
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308221 /* raid transport support */
8222 mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions);
8223 if (!mpt2sas_raid_template) {
8224 sas_release_transport(mpt2sas_transport_template);
8225 return -ENODEV;
8226 }
Eric Moore635374e2009-03-09 01:21:12 -06008227
8228 mpt2sas_base_initialize_callback_handler();
8229
8230 /* queuecommand callback hander */
Eric Moored5d135b2009-05-18 13:02:08 -06008231 scsi_io_cb_idx = mpt2sas_base_register_callback_handler(_scsih_io_done);
Eric Moore635374e2009-03-09 01:21:12 -06008232
Uwe Kleine-König65155b32010-06-11 12:17:01 +02008233 /* task management callback handler */
Eric Moored5d135b2009-05-18 13:02:08 -06008234 tm_cb_idx = mpt2sas_base_register_callback_handler(_scsih_tm_done);
Eric Moore635374e2009-03-09 01:21:12 -06008235
8236 /* base internal commands callback handler */
8237 base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308238 port_enable_cb_idx = mpt2sas_base_register_callback_handler(
8239 mpt2sas_port_enable_done);
Eric Moore635374e2009-03-09 01:21:12 -06008240
8241 /* transport internal commands callback handler */
8242 transport_cb_idx = mpt2sas_base_register_callback_handler(
8243 mpt2sas_transport_done);
8244
Kashyap, Desai744090d2009-10-05 15:56:56 +05308245 /* scsih internal commands callback handler */
8246 scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done);
8247
Eric Moore635374e2009-03-09 01:21:12 -06008248 /* configuration page API internal commands callback handler */
8249 config_cb_idx = mpt2sas_base_register_callback_handler(
8250 mpt2sas_config_done);
8251
8252 /* ctl module callback handler */
8253 ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done);
8254
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308255 tm_tr_cb_idx = mpt2sas_base_register_callback_handler(
8256 _scsih_tm_tr_complete);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05308257
8258 tm_tr_volume_cb_idx = mpt2sas_base_register_callback_handler(
8259 _scsih_tm_volume_tr_complete);
8260
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308261 tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler(
8262 _scsih_sas_control_complete);
8263
Eric Moore635374e2009-03-09 01:21:12 -06008264 mpt2sas_ctl_init();
8265
8266 error = pci_register_driver(&scsih_driver);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308267 if (error) {
8268 /* raid transport support */
8269 raid_class_release(mpt2sas_raid_template);
Eric Moore635374e2009-03-09 01:21:12 -06008270 sas_release_transport(mpt2sas_transport_template);
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308271 }
Eric Moore635374e2009-03-09 01:21:12 -06008272
8273 return error;
8274}
8275
8276/**
Eric Moored5d135b2009-05-18 13:02:08 -06008277 * _scsih_exit - exit point for this driver (when it is a module).
Eric Moore635374e2009-03-09 01:21:12 -06008278 *
8279 * Returns 0 success, anything else error.
8280 */
8281static void __exit
Eric Moored5d135b2009-05-18 13:02:08 -06008282_scsih_exit(void)
Eric Moore635374e2009-03-09 01:21:12 -06008283{
8284 printk(KERN_INFO "mpt2sas version %s unloading\n",
8285 MPT2SAS_DRIVER_VERSION);
8286
8287 pci_unregister_driver(&scsih_driver);
8288
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308289 mpt2sas_ctl_exit();
8290
Eric Moore635374e2009-03-09 01:21:12 -06008291 mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
8292 mpt2sas_base_release_callback_handler(tm_cb_idx);
8293 mpt2sas_base_release_callback_handler(base_cb_idx);
nagalakshmi.nandigama@lsi.com921cd802011-10-19 15:36:26 +05308294 mpt2sas_base_release_callback_handler(port_enable_cb_idx);
Eric Moore635374e2009-03-09 01:21:12 -06008295 mpt2sas_base_release_callback_handler(transport_cb_idx);
Kashyap, Desai744090d2009-10-05 15:56:56 +05308296 mpt2sas_base_release_callback_handler(scsih_cb_idx);
Eric Moore635374e2009-03-09 01:21:12 -06008297 mpt2sas_base_release_callback_handler(config_cb_idx);
8298 mpt2sas_base_release_callback_handler(ctl_cb_idx);
8299
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308300 mpt2sas_base_release_callback_handler(tm_tr_cb_idx);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05308301 mpt2sas_base_release_callback_handler(tm_tr_volume_cb_idx);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05308302 mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx);
8303
Kashyap, Desaif7c95ef2009-12-16 18:54:42 +05308304 /* raid transport support */
8305 raid_class_release(mpt2sas_raid_template);
8306 sas_release_transport(mpt2sas_transport_template);
8307
Eric Moore635374e2009-03-09 01:21:12 -06008308}
8309
Eric Moored5d135b2009-05-18 13:02:08 -06008310module_init(_scsih_init);
8311module_exit(_scsih_exit);