[SCSI] mptsas : Sanity check for phyinfo is added
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
2 * linux/drivers/message/fusion/mptsas.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
0c33b27d 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
0c33b27d
CH
8 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
30
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
48#include <linux/init.h>
49#include <linux/errno.h>
cd354f1a 50#include <linux/jiffies.h>
0c33b27d 51#include <linux/workqueue.h>
547f9a21 52#include <linux/delay.h> /* for mdelay */
0c33b27d 53
547f9a21 54#include <scsi/scsi.h>
0c33b27d
CH
55#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
57#include <scsi/scsi_host.h>
58#include <scsi/scsi_transport_sas.h>
547f9a21 59#include <scsi/scsi_dbg.h>
0c33b27d
CH
60
61#include "mptbase.h"
62#include "mptscsih.h"
56af97ae 63#include "mptsas.h"
0c33b27d
CH
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
e8bf3941
JB
70/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
4b97650b 75#define SAS_CONFIG_PAGE_TIMEOUT 30
0c33b27d
CH
76MODULE_AUTHOR(MODULEAUTHOR);
77MODULE_DESCRIPTION(my_NAME);
78MODULE_LICENSE("GPL");
9f4203b3 79MODULE_VERSION(my_VERSION);
0c33b27d 80
0c33b27d
CH
81static int mpt_pt_clear;
82module_param(mpt_pt_clear, int, 0);
83MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 84 " Clear persistency table: enable=1 "
0c33b27d
CH
85 "(default=MPTSCSIH_PT_CLEAR=0)");
86
793955f5
EM
87/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
88#define MPTSAS_MAX_LUN (16895)
89static int max_lun = MPTSAS_MAX_LUN;
90module_param(max_lun, int, 0);
91MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
92
f606f571
PS
93static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
95static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
96static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
e7deff33 97static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
0c33b27d 98
3eb0822c
KD
99static void mptsas_firmware_event_work(struct work_struct *work);
100static void mptsas_send_sas_event(struct fw_event_work *fw_event);
101static void mptsas_send_raid_event(struct fw_event_work *fw_event);
102static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
103static void mptsas_parse_device_info(struct sas_identify *identify,
104 struct mptsas_devinfo *device_info);
105static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
106 struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
107static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address
108 (MPT_ADAPTER *ioc, u64 sas_address);
109static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
110 struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
111static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
112 struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
113static int mptsas_add_end_device(MPT_ADAPTER *ioc,
114 struct mptsas_phyinfo *phy_info);
115static void mptsas_del_end_device(MPT_ADAPTER *ioc,
116 struct mptsas_phyinfo *phy_info);
f9c34022
KD
117static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
118static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
119 (MPT_ADAPTER *ioc, u64 sas_address);
120static void mptsas_expander_delete(MPT_ADAPTER *ioc,
121 struct mptsas_portinfo *port_info, u8 force);
122static void mptsas_send_expander_event(struct fw_event_work *fw_event);
eedf92b9
KD
123static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
124static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
db7051b2 125static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
57e98513 126static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
a7938b0b 127static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
0c33b27d 128
d6ecdd63
PS
129static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
130 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
131{
29dd3609
EM
132 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
133 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
135 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
137 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
138 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
139 ioc->name, phy_data->Port));
140 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
141 ioc->name, phy_data->PortFlags));
142 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
143 ioc->name, phy_data->PhyFlags));
144 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
145 ioc->name, phy_data->NegotiatedLinkRate));
146 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
147 "Controller PHY Device Info=0x%X\n", ioc->name,
148 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
149 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
150 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
151}
152
d6ecdd63 153static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
154{
155 __le64 sas_address;
156
157 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
158
29dd3609
EM
159 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
160 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
161 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
162 "Attached Device Handle=0x%X\n", ioc->name,
163 le16_to_cpu(pg0->AttachedDevHandle)));
164 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
165 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
166 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
167 "Attached PHY Identifier=0x%X\n", ioc->name,
168 pg0->AttachedPhyIdentifier));
169 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
170 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
171 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
172 ioc->name, pg0->ProgrammedLinkRate));
173 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
174 ioc->name, pg0->ChangeCount));
175 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
176 ioc->name, le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
177}
178
d6ecdd63 179static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 180{
29dd3609
EM
181 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
182 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
183 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
184 ioc->name, pg1->InvalidDwordCount));
185 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
186 "Running Disparity Error Count=0x%x\n", ioc->name,
187 pg1->RunningDisparityErrorCount));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
189 "Loss Dword Synch Count=0x%x\n", ioc->name,
190 pg1->LossDwordSynchCount));
191 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
192 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
193 pg1->PhyResetProblemCount));
b5141128
CH
194}
195
d6ecdd63 196static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
197{
198 __le64 sas_address;
199
200 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
201
29dd3609
EM
202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
203 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
205 ioc->name, le16_to_cpu(pg0->DevHandle)));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
207 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
209 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
211 ioc->name, le16_to_cpu(pg0->Slot)));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
213 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
215 ioc->name, pg0->TargetID));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
217 ioc->name, pg0->Bus));
218 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
219 ioc->name, pg0->PhyNum));
220 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
221 ioc->name, le16_to_cpu(pg0->AccessStatus)));
222 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
223 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
224 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
225 ioc->name, le16_to_cpu(pg0->Flags)));
226 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
227 ioc->name, pg0->PhysicalPort));
b5141128
CH
228}
229
d6ecdd63
PS
230static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
231{
29dd3609
EM
232 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
233 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
234 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
235 ioc->name, pg1->PhysicalPort));
236 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
237 ioc->name, pg1->PhyIdentifier));
238 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
239 ioc->name, pg1->NegotiatedLinkRate));
240 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
241 ioc->name, pg1->ProgrammedLinkRate));
242 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
243 ioc->name, pg1->HwLinkRate));
244 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
245 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
246 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
247 "Attached Device Handle=0x%X\n\n", ioc->name,
248 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 249}
b5141128 250
3eb0822c
KD
251/* inhibit sas firmware event handling */
252static void
253mptsas_fw_event_off(MPT_ADAPTER *ioc)
254{
255 unsigned long flags;
256
257 spin_lock_irqsave(&ioc->fw_event_lock, flags);
258 ioc->fw_events_off = 1;
259 ioc->sas_discovery_quiesce_io = 0;
260 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
261
262}
263
264/* enable sas firmware event handling */
265static void
266mptsas_fw_event_on(MPT_ADAPTER *ioc)
267{
268 unsigned long flags;
269
270 spin_lock_irqsave(&ioc->fw_event_lock, flags);
271 ioc->fw_events_off = 0;
272 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
273}
274
275/* queue a sas firmware event */
276static void
277mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
278 unsigned long delay)
279{
280 unsigned long flags;
281
282 spin_lock_irqsave(&ioc->fw_event_lock, flags);
283 list_add_tail(&fw_event->list, &ioc->fw_event_list);
284 INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
285 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
286 ioc->name, __func__, fw_event));
287 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
288 delay);
289 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
290}
291
db7051b2
KD
292/* requeue a sas firmware event */
293static void
294mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
295 unsigned long delay)
296{
297 unsigned long flags;
298 spin_lock_irqsave(&ioc->fw_event_lock, flags);
299 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
300 "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
301 fw_event->retries++;
302 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
303 msecs_to_jiffies(delay));
304 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
305}
306
3eb0822c
KD
307/* free memory assoicated to a sas firmware event */
308static void
309mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
310{
311 unsigned long flags;
312
313 spin_lock_irqsave(&ioc->fw_event_lock, flags);
314 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
315 ioc->name, __func__, fw_event));
316 list_del(&fw_event->list);
317 kfree(fw_event);
318 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
319}
320
321/* walk the firmware event queue, and either stop or wait for
322 * outstanding events to complete */
323static void
324mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
325{
326 struct fw_event_work *fw_event, *next;
327 struct mptsas_target_reset_event *target_reset_list, *n;
328 u8 flush_q;
329 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
330
331 /* flush the target_reset_list */
332 if (!list_empty(&hd->target_reset_list)) {
333 list_for_each_entry_safe(target_reset_list, n,
334 &hd->target_reset_list, list) {
335 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
336 "%s: removing target reset for id=%d\n",
337 ioc->name, __func__,
338 target_reset_list->sas_event_data.TargetID));
339 list_del(&target_reset_list->list);
340 kfree(target_reset_list);
341 }
342 }
343
344 if (list_empty(&ioc->fw_event_list) ||
345 !ioc->fw_event_q || in_interrupt())
346 return;
347
348 flush_q = 0;
349 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
350 if (cancel_delayed_work(&fw_event->work))
351 mptsas_free_fw_event(ioc, fw_event);
352 else
353 flush_q = 1;
354 }
355 if (flush_q)
356 flush_workqueue(ioc->fw_event_q);
357}
358
359
e3094447
CH
360static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
361{
362 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
363 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
364}
365
366static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
367{
368 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
369 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
370}
371
e6b2d76a
ME
372/*
373 * mptsas_find_portinfo_by_handle
374 *
375 * This function should be called with the sas_topology_mutex already held
376 */
377static struct mptsas_portinfo *
378mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
379{
380 struct mptsas_portinfo *port_info, *rc=NULL;
381 int i;
382
383 list_for_each_entry(port_info, &ioc->sas_topology, list)
384 for (i = 0; i < port_info->num_phys; i++)
385 if (port_info->phy_info[i].identify.handle == handle) {
386 rc = port_info;
387 goto out;
388 }
389 out:
390 return rc;
391}
392
f9c34022
KD
393/**
394 * mptsas_find_portinfo_by_sas_address -
395 * @ioc: Pointer to MPT_ADAPTER structure
396 * @handle:
397 *
398 * This function should be called with the sas_topology_mutex already held
399 *
400 **/
401static struct mptsas_portinfo *
402mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
403{
404 struct mptsas_portinfo *port_info, *rc = NULL;
405 int i;
406
407 if (sas_address >= ioc->hba_port_sas_addr &&
408 sas_address < (ioc->hba_port_sas_addr +
409 ioc->hba_port_num_phy))
410 return ioc->hba_port_info;
411
412 mutex_lock(&ioc->sas_topology_mutex);
413 list_for_each_entry(port_info, &ioc->sas_topology, list)
414 for (i = 0; i < port_info->num_phys; i++)
415 if (port_info->phy_info[i].identify.sas_address ==
416 sas_address) {
417 rc = port_info;
418 goto out;
419 }
420 out:
421 mutex_unlock(&ioc->sas_topology_mutex);
422 return rc;
423}
424
bd23e94c
ME
425/*
426 * Returns true if there is a scsi end device
427 */
428static inline int
429mptsas_is_end_device(struct mptsas_devinfo * attached)
430{
547f9a21 431 if ((attached->sas_address) &&
bd23e94c
ME
432 (attached->device_info &
433 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
434 ((attached->device_info &
435 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
436 (attached->device_info &
437 MPI_SAS_DEVICE_INFO_STP_TARGET) |
438 (attached->device_info &
439 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
440 return 1;
441 else
442 return 0;
443}
444
547f9a21 445/* no mutex */
376ac830 446static void
d6ecdd63 447mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
448{
449 struct mptsas_portinfo *port_info;
450 struct mptsas_phyinfo *phy_info;
451 u8 i;
452
453 if (!port_details)
454 return;
455
456 port_info = port_details->port_info;
457 phy_info = port_info->phy_info;
458
29dd3609 459 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
cadbd4a5 460 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
f99be43b
EM
461 port_details->num_phys, (unsigned long long)
462 port_details->phy_bitmask));
547f9a21
EM
463
464 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
465 if(phy_info->port_details != port_details)
466 continue;
467 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
3eb0822c 468 mptsas_set_rphy(ioc, phy_info, NULL);
547f9a21
EM
469 phy_info->port_details = NULL;
470 }
471 kfree(port_details);
472}
473
474static inline struct sas_rphy *
475mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
476{
477 if (phy_info->port_details)
478 return phy_info->port_details->rphy;
479 else
480 return NULL;
481}
482
483static inline void
d6ecdd63 484mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
485{
486 if (phy_info->port_details) {
487 phy_info->port_details->rphy = rphy;
29dd3609
EM
488 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
489 ioc->name, rphy));
547f9a21
EM
490 }
491
547f9a21 492 if (rphy) {
c51d0bea
EM
493 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
494 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
495 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
496 ioc->name, rphy, rphy->dev.release));
547f9a21 497 }
547f9a21
EM
498}
499
500static inline struct sas_port *
501mptsas_get_port(struct mptsas_phyinfo *phy_info)
502{
503 if (phy_info->port_details)
504 return phy_info->port_details->port;
505 else
506 return NULL;
507}
508
509static inline void
d6ecdd63 510mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
511{
512 if (phy_info->port_details)
513 phy_info->port_details->port = port;
514
547f9a21 515 if (port) {
c51d0bea
EM
516 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
517 &port->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
518 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
519 ioc->name, port, port->dev.release));
547f9a21 520 }
547f9a21
EM
521}
522
523static inline struct scsi_target *
524mptsas_get_starget(struct mptsas_phyinfo *phy_info)
525{
526 if (phy_info->port_details)
527 return phy_info->port_details->starget;
528 else
529 return NULL;
530}
531
532static inline void
533mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
534starget)
535{
536 if (phy_info->port_details)
537 phy_info->port_details->starget = starget;
538}
539
3eb0822c
KD
540/**
541 * mptsas_add_device_component -
542 * @ioc: Pointer to MPT_ADAPTER structure
543 * @channel: fw mapped id's
544 * @id:
545 * @sas_address:
546 * @device_info:
547 *
548 **/
549static void
550mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
551 u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
552{
553 struct mptsas_device_info *sas_info, *next;
554 struct scsi_device *sdev;
555 struct scsi_target *starget;
556 struct sas_rphy *rphy;
557
558 /*
559 * Delete all matching devices out of the list
560 */
561 mutex_lock(&ioc->sas_device_info_mutex);
562 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
563 list) {
a7938b0b
KD
564 if (!sas_info->is_logical_volume &&
565 (sas_info->sas_address == sas_address ||
566 (sas_info->fw.channel == channel &&
567 sas_info->fw.id == id))) {
3eb0822c
KD
568 list_del(&sas_info->list);
569 kfree(sas_info);
570 }
571 }
572
573 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
574 if (!sas_info)
575 goto out;
576
577 /*
578 * Set Firmware mapping
579 */
580 sas_info->fw.id = id;
581 sas_info->fw.channel = channel;
582
583 sas_info->sas_address = sas_address;
584 sas_info->device_info = device_info;
585 sas_info->slot = slot;
586 sas_info->enclosure_logical_id = enclosure_logical_id;
587 INIT_LIST_HEAD(&sas_info->list);
588 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
589
590 /*
591 * Set OS mapping
592 */
593 shost_for_each_device(sdev, ioc->sh) {
594 starget = scsi_target(sdev);
595 rphy = dev_to_rphy(starget->dev.parent);
596 if (rphy->identify.sas_address == sas_address) {
597 sas_info->os.id = starget->id;
598 sas_info->os.channel = starget->channel;
599 }
600 }
601
602 out:
603 mutex_unlock(&ioc->sas_device_info_mutex);
604 return;
605}
606
607/**
608 * mptsas_add_device_component_by_fw -
609 * @ioc: Pointer to MPT_ADAPTER structure
610 * @channel: fw mapped id's
611 * @id:
612 *
613 **/
614static void
615mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
616{
617 struct mptsas_devinfo sas_device;
618 struct mptsas_enclosure enclosure_info;
619 int rc;
620
621 rc = mptsas_sas_device_pg0(ioc, &sas_device,
622 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
623 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
624 (channel << 8) + id);
625 if (rc)
626 return;
627
628 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
629 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
630 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
631 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
632 sas_device.handle_enclosure);
633
634 mptsas_add_device_component(ioc, sas_device.channel,
635 sas_device.id, sas_device.sas_address, sas_device.device_info,
636 sas_device.slot, enclosure_info.enclosure_logical_id);
637}
638
a7938b0b 639/**
fc847ab4 640 * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
a7938b0b
KD
641 * @ioc: Pointer to MPT_ADAPTER structure
642 * @channel: fw mapped id's
643 * @id:
644 *
645 **/
646static void
647mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
648 struct scsi_target *starget)
649{
650 CONFIGPARMS cfg;
651 ConfigPageHeader_t hdr;
652 dma_addr_t dma_handle;
653 pRaidVolumePage0_t buffer = NULL;
654 int i;
655 RaidPhysDiskPage0_t phys_disk;
656 struct mptsas_device_info *sas_info, *next;
657
658 memset(&cfg, 0 , sizeof(CONFIGPARMS));
659 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
660 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
661 /* assumption that all volumes on channel = 0 */
662 cfg.pageAddr = starget->id;
663 cfg.cfghdr.hdr = &hdr;
664 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4b97650b 665 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
a7938b0b
KD
666
667 if (mpt_config(ioc, &cfg) != 0)
668 goto out;
669
670 if (!hdr.PageLength)
671 goto out;
672
673 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
674 &dma_handle);
675
676 if (!buffer)
677 goto out;
678
679 cfg.physAddr = dma_handle;
680 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
681
682 if (mpt_config(ioc, &cfg) != 0)
683 goto out;
684
685 if (!buffer->NumPhysDisks)
686 goto out;
687
688 /*
689 * Adding entry for hidden components
690 */
691 for (i = 0; i < buffer->NumPhysDisks; i++) {
692
693 if (mpt_raid_phys_disk_pg0(ioc,
694 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
695 continue;
696
697 mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
698 phys_disk.PhysDiskID);
699
57e98513
KD
700 mutex_lock(&ioc->sas_device_info_mutex);
701 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
702 list) {
703 if (!sas_info->is_logical_volume &&
704 (sas_info->fw.channel == phys_disk.PhysDiskBus &&
705 sas_info->fw.id == phys_disk.PhysDiskID)) {
706 sas_info->is_hidden_raid_component = 1;
707 sas_info->volume_id = starget->id;
708 }
709 }
710 mutex_unlock(&ioc->sas_device_info_mutex);
711
a7938b0b
KD
712 }
713
714 /*
715 * Delete all matching devices out of the list
716 */
717 mutex_lock(&ioc->sas_device_info_mutex);
718 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
719 list) {
720 if (sas_info->is_logical_volume && sas_info->fw.id ==
721 starget->id) {
722 list_del(&sas_info->list);
723 kfree(sas_info);
724 }
725 }
726
727 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
728 if (sas_info) {
729 sas_info->fw.id = starget->id;
730 sas_info->os.id = starget->id;
731 sas_info->os.channel = starget->channel;
732 sas_info->is_logical_volume = 1;
733 INIT_LIST_HEAD(&sas_info->list);
734 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
735 }
736 mutex_unlock(&ioc->sas_device_info_mutex);
737
738 out:
739 if (buffer)
740 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
741 dma_handle);
742}
743
3eb0822c
KD
744/**
745 * mptsas_add_device_component_starget -
746 * @ioc: Pointer to MPT_ADAPTER structure
747 * @starget:
748 *
749 **/
750static void
751mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
752 struct scsi_target *starget)
753{
754 VirtTarget *vtarget;
755 struct sas_rphy *rphy;
756 struct mptsas_phyinfo *phy_info = NULL;
757 struct mptsas_enclosure enclosure_info;
758
759 rphy = dev_to_rphy(starget->dev.parent);
760 vtarget = starget->hostdata;
761 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
762 rphy->identify.sas_address);
763 if (!phy_info)
764 return;
765
766 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
767 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
768 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
769 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
770 phy_info->attached.handle_enclosure);
771
772 mptsas_add_device_component(ioc, phy_info->attached.channel,
773 phy_info->attached.id, phy_info->attached.sas_address,
774 phy_info->attached.device_info,
775 phy_info->attached.slot, enclosure_info.enclosure_logical_id);
776}
777
57e98513 778/**
fc847ab4 779 * mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
57e98513
KD
780 * @ioc: Pointer to MPT_ADAPTER structure
781 * @channel: os mapped id's
782 * @id:
783 *
784 **/
785static void
786mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
787{
788 struct mptsas_device_info *sas_info, *next;
789
790 /*
791 * Set is_cached flag
792 */
793 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
794 list) {
795 if (sas_info->os.channel == channel && sas_info->os.id == id)
796 sas_info->is_cached = 1;
797 }
798}
799
3eb0822c
KD
800/**
801 * mptsas_del_device_components - Cleaning the list
802 * @ioc: Pointer to MPT_ADAPTER structure
803 *
804 **/
805static void
806mptsas_del_device_components(MPT_ADAPTER *ioc)
807{
808 struct mptsas_device_info *sas_info, *next;
809
810 mutex_lock(&ioc->sas_device_info_mutex);
811 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
812 list) {
813 list_del(&sas_info->list);
814 kfree(sas_info);
815 }
816 mutex_unlock(&ioc->sas_device_info_mutex);
817}
818
547f9a21
EM
819
820/*
821 * mptsas_setup_wide_ports
822 *
823 * Updates for new and existing narrow/wide port configuration
824 * in the sas_topology
825 */
376ac830 826static void
547f9a21
EM
827mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
828{
829 struct mptsas_portinfo_details * port_details;
830 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
831 u64 sas_address;
832 int i, j;
833
834 mutex_lock(&ioc->sas_topology_mutex);
835
836 phy_info = port_info->phy_info;
837 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
838 if (phy_info->attached.handle)
839 continue;
840 port_details = phy_info->port_details;
841 if (!port_details)
842 continue;
843 if (port_details->num_phys < 2)
844 continue;
845 /*
846 * Removing a phy from a port, letting the last
847 * phy be removed by firmware events.
848 */
29dd3609
EM
849 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
850 "%s: [%p]: deleting phy = %d\n",
cadbd4a5 851 ioc->name, __func__, port_details, i));
547f9a21
EM
852 port_details->num_phys--;
853 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
854 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
9e39089b
KD
855 if (phy_info->phy) {
856 devtprintk(ioc, dev_printk(KERN_DEBUG,
857 &phy_info->phy->dev, MYIOC_s_FMT
858 "delete phy %d, phy-obj (0x%p)\n", ioc->name,
859 phy_info->phy_id, phy_info->phy));
860 sas_port_delete_phy(port_details->port, phy_info->phy);
861 }
547f9a21
EM
862 phy_info->port_details = NULL;
863 }
864
865 /*
866 * Populate and refresh the tree
867 */
868 phy_info = port_info->phy_info;
869 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
870 sas_address = phy_info->attached.sas_address;
29dd3609
EM
871 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
872 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
873 if (!sas_address)
874 continue;
875 port_details = phy_info->port_details;
876 /*
877 * Forming a port
878 */
879 if (!port_details) {
2f187862
KD
880 port_details = kzalloc(sizeof(struct
881 mptsas_portinfo_details), GFP_KERNEL);
547f9a21
EM
882 if (!port_details)
883 goto out;
884 port_details->num_phys = 1;
885 port_details->port_info = port_info;
547f9a21
EM
886 if (phy_info->phy_id < 64 )
887 port_details->phy_bitmask |=
888 (1 << phy_info->phy_id);
889 phy_info->sas_port_add_phy=1;
29dd3609 890 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
f99be43b 891 "phy_id=%d sas_address=0x%018llX\n",
29dd3609 892 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
893 phy_info->port_details = port_details;
894 }
895
896 if (i == port_info->num_phys - 1)
897 continue;
898 phy_info_cmp = &port_info->phy_info[i + 1];
899 for (j = i + 1 ; j < port_info->num_phys ; j++,
900 phy_info_cmp++) {
901 if (!phy_info_cmp->attached.sas_address)
902 continue;
903 if (sas_address != phy_info_cmp->attached.sas_address)
904 continue;
905 if (phy_info_cmp->port_details == port_details )
906 continue;
29dd3609 907 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 908 "\t\tphy_id=%d sas_address=0x%018llX\n",
29dd3609 909 ioc->name, j, (unsigned long long)
f99be43b 910 phy_info_cmp->attached.sas_address));
547f9a21
EM
911 if (phy_info_cmp->port_details) {
912 port_details->rphy =
913 mptsas_get_rphy(phy_info_cmp);
914 port_details->port =
915 mptsas_get_port(phy_info_cmp);
916 port_details->starget =
917 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
918 port_details->num_phys =
919 phy_info_cmp->port_details->num_phys;
547f9a21
EM
920 if (!phy_info_cmp->port_details->num_phys)
921 kfree(phy_info_cmp->port_details);
922 } else
923 phy_info_cmp->sas_port_add_phy=1;
924 /*
925 * Adding a phy to a port
926 */
927 phy_info_cmp->port_details = port_details;
928 if (phy_info_cmp->phy_id < 64 )
929 port_details->phy_bitmask |=
930 (1 << phy_info_cmp->phy_id);
931 port_details->num_phys++;
932 }
933 }
934
935 out:
936
547f9a21
EM
937 for (i = 0; i < port_info->num_phys; i++) {
938 port_details = port_info->phy_info[i].port_details;
939 if (!port_details)
940 continue;
29dd3609 941 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 942 "%s: [%p]: phy_id=%02d num_phys=%02d "
cadbd4a5 943 "bitmask=0x%016llX\n", ioc->name, __func__,
f99be43b
EM
944 port_details, i, port_details->num_phys,
945 (unsigned long long)port_details->phy_bitmask));
29dd3609
EM
946 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
947 ioc->name, port_details->port, port_details->rphy));
547f9a21 948 }
29dd3609 949 dsaswideprintk(ioc, printk("\n"));
547f9a21
EM
950 mutex_unlock(&ioc->sas_topology_mutex);
951}
952
df9e062a
EM
953/**
954 * csmisas_find_vtarget
955 *
956 * @ioc
957 * @volume_id
958 * @volume_bus
959 *
960 **/
961static VirtTarget *
962mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
963{
964 struct scsi_device *sdev;
a69de507 965 VirtDevice *vdevice;
df9e062a
EM
966 VirtTarget *vtarget = NULL;
967
968 shost_for_each_device(sdev, ioc->sh) {
e7deff33
KD
969 vdevice = sdev->hostdata;
970 if ((vdevice == NULL) ||
971 (vdevice->vtarget == NULL))
df9e062a 972 continue;
a7938b0b
KD
973 if ((vdevice->vtarget->tflags &
974 MPT_TARGET_FLAGS_RAID_COMPONENT ||
975 vdevice->vtarget->raidVolume))
976 continue;
a69de507 977 if (vdevice->vtarget->id == id &&
e7deff33 978 vdevice->vtarget->channel == channel)
a69de507 979 vtarget = vdevice->vtarget;
df9e062a
EM
980 }
981 return vtarget;
982}
983
3eb0822c
KD
984static void
985mptsas_queue_device_delete(MPT_ADAPTER *ioc,
986 MpiEventDataSasDeviceStatusChange_t *sas_event_data)
987{
988 struct fw_event_work *fw_event;
989 int sz;
990
991 sz = offsetof(struct fw_event_work, event_data) +
992 sizeof(MpiEventDataSasDeviceStatusChange_t);
993 fw_event = kzalloc(sz, GFP_ATOMIC);
994 if (!fw_event) {
995 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
996 ioc->name, __func__, __LINE__);
997 return;
998 }
999 memcpy(fw_event->event_data, sas_event_data,
1000 sizeof(MpiEventDataSasDeviceStatusChange_t));
1001 fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
1002 fw_event->ioc = ioc;
1003 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1004}
1005
eedf92b9
KD
1006static void
1007mptsas_queue_rescan(MPT_ADAPTER *ioc)
1008{
1009 struct fw_event_work *fw_event;
1010 int sz;
1011
1012 sz = offsetof(struct fw_event_work, event_data);
1013 fw_event = kzalloc(sz, GFP_ATOMIC);
1014 if (!fw_event) {
1015 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1016 ioc->name, __func__, __LINE__);
1017 return;
1018 }
1019 fw_event->event = -1;
1020 fw_event->ioc = ioc;
1021 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1022}
1023
3eb0822c 1024
df9e062a
EM
1025/**
1026 * mptsas_target_reset
1027 *
1028 * Issues TARGET_RESET to end device using handshaking method
1029 *
1030 * @ioc
1031 * @channel
1032 * @id
1033 *
1034 * Returns (1) success
1035 * (0) failure
1036 *
1037 **/
1038static int
1039mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1040{
1041 MPT_FRAME_HDR *mf;
1042 SCSITaskMgmt_t *pScsiTm;
ea2a788d
KD
1043 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
1044 return 0;
1045
df9e062a 1046
e7deff33
KD
1047 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
1048 if (mf == NULL) {
1049 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
ea2a788d
KD
1050 "%s, no msg frames @%d!!\n", ioc->name,
1051 __func__, __LINE__));
1052 goto out_fail;
df9e062a
EM
1053 }
1054
ea2a788d
KD
1055 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1056 ioc->name, mf));
1057
df9e062a
EM
1058 /* Format the Request
1059 */
1060 pScsiTm = (SCSITaskMgmt_t *) mf;
1061 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
1062 pScsiTm->TargetID = id;
1063 pScsiTm->Bus = channel;
1064 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1065 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1066 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
1067
d6ecdd63 1068 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 1069
ea2a788d
KD
1070 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1071 "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
1072 ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
1073
e7deff33 1074 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
df9e062a
EM
1075
1076 return 1;
ea2a788d
KD
1077
1078 out_fail:
1079
1080 mpt_clear_taskmgmt_in_progress_flag(ioc);
1081 return 0;
df9e062a
EM
1082}
1083
1084/**
1085 * mptsas_target_reset_queue
1086 *
1087 * Receive request for TARGET_RESET after recieving an firmware
1088 * event NOT_RESPONDING_EVENT, then put command in link list
1089 * and queue if task_queue already in use.
1090 *
1091 * @ioc
1092 * @sas_event_data
1093 *
1094 **/
547f9a21 1095static void
df9e062a
EM
1096mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1097 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 1098{
e7eae9f6 1099 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
1100 VirtTarget *vtarget = NULL;
1101 struct mptsas_target_reset_event *target_reset_list;
1102 u8 id, channel;
547f9a21 1103
df9e062a
EM
1104 id = sas_event_data->TargetID;
1105 channel = sas_event_data->Bus;
1106
1107 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
1108 return;
1109
1110 vtarget->deleted = 1; /* block IO */
1111
2f187862 1112 target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
df9e062a
EM
1113 GFP_ATOMIC);
1114 if (!target_reset_list) {
e7deff33
KD
1115 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1116 "%s, failed to allocate mem @%d..!!\n",
1117 ioc->name, __func__, __LINE__));
df9e062a
EM
1118 return;
1119 }
1120
1121 memcpy(&target_reset_list->sas_event_data, sas_event_data,
1122 sizeof(*sas_event_data));
1123 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
1124
e7deff33 1125 target_reset_list->time_count = jiffies;
df9e062a
EM
1126
1127 if (mptsas_target_reset(ioc, channel, id)) {
1128 target_reset_list->target_reset_issued = 1;
df9e062a
EM
1129 }
1130}
1131
1132/**
fc847ab4 1133 * mptsas_taskmgmt_complete - complete SAS task management function
e7deff33 1134 * @ioc: Pointer to MPT_ADAPTER structure
df9e062a 1135 *
fc847ab4
JB
1136 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
1137 * queue to finish off removing device from upper layers. then send next
1138 * TARGET_RESET in the queue.
df9e062a 1139 **/
e7deff33
KD
1140static int
1141mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
df9e062a 1142{
e7eae9f6 1143 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a 1144 struct list_head *head = &hd->target_reset_list;
df9e062a 1145 u8 id, channel;
e7deff33
KD
1146 struct mptsas_target_reset_event *target_reset_list;
1147 SCSITaskMgmtReply_t *pScsiTmReply;
1148
1149 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
1150 "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
1151
1152 pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
1153 if (pScsiTmReply) {
1154 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1155 "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
1156 "\ttask_type = 0x%02X, iocstatus = 0x%04X "
1157 "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
1158 "term_cmnds = %d\n", ioc->name,
1159 pScsiTmReply->Bus, pScsiTmReply->TargetID,
1160 pScsiTmReply->TaskType,
1161 le16_to_cpu(pScsiTmReply->IOCStatus),
1162 le32_to_cpu(pScsiTmReply->IOCLogInfo),
1163 pScsiTmReply->ResponseCode,
1164 le32_to_cpu(pScsiTmReply->TerminationCount)));
1165
1166 if (pScsiTmReply->ResponseCode)
1167 mptscsih_taskmgmt_response_code(ioc,
1168 pScsiTmReply->ResponseCode);
1169 }
1170
1171 if (pScsiTmReply && (pScsiTmReply->TaskType ==
1172 MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
1173 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
1174 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1175 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
1176 memcpy(ioc->taskmgmt_cmds.reply, mr,
1177 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1178 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1179 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1180 complete(&ioc->taskmgmt_cmds.done);
1181 return 1;
1182 }
1183 return 0;
1184 }
1185
1186 mpt_clear_taskmgmt_in_progress_flag(ioc);
df9e062a
EM
1187
1188 if (list_empty(head))
e7deff33
KD
1189 return 1;
1190
1191 target_reset_list = list_entry(head->next,
1192 struct mptsas_target_reset_event, list);
df9e062a 1193
e7deff33
KD
1194 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1195 "TaskMgmt: completed (%d seconds)\n",
1196 ioc->name, jiffies_to_msecs(jiffies -
1197 target_reset_list->time_count)/1000));
df9e062a 1198
e7deff33
KD
1199 id = pScsiTmReply->TargetID;
1200 channel = pScsiTmReply->Bus;
1201 target_reset_list->time_count = jiffies;
df9e062a
EM
1202
1203 /*
1204 * retry target reset
1205 */
1206 if (!target_reset_list->target_reset_issued) {
e7deff33 1207 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1208 target_reset_list->target_reset_issued = 1;
e7deff33 1209 return 1;
df9e062a
EM
1210 }
1211
1212 /*
1213 * enable work queue to remove device from upper layers
1214 */
1215 list_del(&target_reset_list->list);
3eb0822c
KD
1216 if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
1217 mptsas_queue_device_delete(ioc,
1218 &target_reset_list->sas_event_data);
ea2a788d 1219
e7deff33 1220
df9e062a
EM
1221 /*
1222 * issue target reset to next device in the queue
1223 */
1224
1225 head = &hd->target_reset_list;
1226 if (list_empty(head))
e7deff33 1227 return 1;
df9e062a
EM
1228
1229 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
1230 list);
1231
e7deff33
KD
1232 id = target_reset_list->sas_event_data.TargetID;
1233 channel = target_reset_list->sas_event_data.Bus;
1234 target_reset_list->time_count = jiffies;
df9e062a 1235
e7deff33 1236 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1237 target_reset_list->target_reset_issued = 1;
df9e062a 1238
e7deff33 1239 return 1;
df9e062a
EM
1240}
1241
1242/**
1243 * mptscsih_ioc_reset
1244 *
1245 * @ioc
1246 * @reset_phase
1247 *
1248 **/
1249static int
1250mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1251{
ba76ef24 1252 MPT_SCSI_HOST *hd;
df9e062a
EM
1253 int rc;
1254
1255 rc = mptscsih_ioc_reset(ioc, reset_phase);
3eb0822c
KD
1256 if ((ioc->bus_type != SAS) || (!rc))
1257 return rc;
df9e062a 1258
e7eae9f6 1259 hd = shost_priv(ioc->sh);
ba76ef24 1260 if (!hd->ioc)
df9e062a
EM
1261 goto out;
1262
3eb0822c
KD
1263 switch (reset_phase) {
1264 case MPT_IOC_SETUP_RESET:
1265 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1266 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1267 mptsas_fw_event_off(ioc);
1268 break;
1269 case MPT_IOC_PRE_RESET:
1270 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1271 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1272 break;
1273 case MPT_IOC_POST_RESET:
1274 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1275 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1276 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1277 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1278 complete(&ioc->sas_mgmt.done);
1279 }
1280 mptsas_cleanup_fw_event_q(ioc);
eedf92b9 1281 mptsas_queue_rescan(ioc);
3eb0822c
KD
1282 mptsas_fw_event_on(ioc);
1283 break;
1284 default:
1285 break;
547f9a21 1286 }
df9e062a
EM
1287
1288 out:
1289 return rc;
547f9a21
EM
1290}
1291
3eb0822c
KD
1292
1293/**
1294 * enum device_state -
1295 * @DEVICE_RETRY: need to retry the TUR
1296 * @DEVICE_ERROR: TUR return error, don't add device
1297 * @DEVICE_READY: device can be added
1298 *
1299 */
1300enum device_state{
1301 DEVICE_RETRY,
1302 DEVICE_ERROR,
1303 DEVICE_READY,
1304};
1305
e3094447 1306static int
52435430 1307mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
1308 u32 form, u32 form_specific)
1309{
1310 ConfigExtendedPageHeader_t hdr;
1311 CONFIGPARMS cfg;
1312 SasEnclosurePage0_t *buffer;
1313 dma_addr_t dma_handle;
1314 int error;
1315 __le64 le_identifier;
1316
1317 memset(&hdr, 0, sizeof(hdr));
1318 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1319 hdr.PageNumber = 0;
1320 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1321 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1322
1323 cfg.cfghdr.ehdr = &hdr;
1324 cfg.physAddr = -1;
1325 cfg.pageAddr = form + form_specific;
1326 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1327 cfg.dir = 0; /* read */
4b97650b 1328 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
e3094447
CH
1329
1330 error = mpt_config(ioc, &cfg);
1331 if (error)
1332 goto out;
1333 if (!hdr.ExtPageLength) {
1334 error = -ENXIO;
1335 goto out;
1336 }
1337
1338 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1339 &dma_handle);
1340 if (!buffer) {
1341 error = -ENOMEM;
1342 goto out;
1343 }
1344
1345 cfg.physAddr = dma_handle;
1346 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1347
1348 error = mpt_config(ioc, &cfg);
1349 if (error)
1350 goto out_free_consistent;
1351
1352 /* save config data */
1353 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1354 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1355 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1356 enclosure->flags = le16_to_cpu(buffer->Flags);
1357 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1358 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1359 enclosure->start_id = buffer->StartTargetID;
1360 enclosure->start_channel = buffer->StartBus;
1361 enclosure->sep_id = buffer->SEPTargetID;
1362 enclosure->sep_channel = buffer->SEPBus;
1363
1364 out_free_consistent:
1365 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1366 buffer, dma_handle);
1367 out:
1368 return error;
1369}
b5141128 1370
3eb0822c
KD
1371/**
1372 * mptsas_add_end_device - report a new end device to sas transport layer
1373 * @ioc: Pointer to MPT_ADAPTER structure
1374 * @phy_info: decribes attached device
1375 *
1376 * return (0) success (1) failure
1377 *
1378 **/
1379static int
1380mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1381{
1382 struct sas_rphy *rphy;
1383 struct sas_port *port;
1384 struct sas_identify identify;
1385 char *ds = NULL;
1386 u8 fw_id;
1387
1388 if (!phy_info) {
1389 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1390 "%s: exit at line=%d\n", ioc->name,
1391 __func__, __LINE__));
1392 return 1;
1393 }
1394
1395 fw_id = phy_info->attached.id;
1396
1397 if (mptsas_get_rphy(phy_info)) {
1398 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1399 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1400 __func__, fw_id, __LINE__));
1401 return 2;
1402 }
1403
1404 port = mptsas_get_port(phy_info);
1405 if (!port) {
1406 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1407 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1408 __func__, fw_id, __LINE__));
1409 return 3;
1410 }
1411
1412 if (phy_info->attached.device_info &
1413 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1414 ds = "ssp";
1415 if (phy_info->attached.device_info &
1416 MPI_SAS_DEVICE_INFO_STP_TARGET)
1417 ds = "stp";
1418 if (phy_info->attached.device_info &
1419 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1420 ds = "sata";
1421
1422 printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1423 " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1424 phy_info->attached.channel, phy_info->attached.id,
1425 phy_info->attached.phy_id, (unsigned long long)
1426 phy_info->attached.sas_address);
1427
1428 mptsas_parse_device_info(&identify, &phy_info->attached);
1429 rphy = sas_end_device_alloc(port);
1430 if (!rphy) {
1431 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1432 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1433 __func__, fw_id, __LINE__));
1434 return 5; /* non-fatal: an rphy can be added later */
1435 }
1436
1437 rphy->identify = identify;
1438 if (sas_rphy_add(rphy)) {
1439 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1440 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1441 __func__, fw_id, __LINE__));
1442 sas_rphy_free(rphy);
1443 return 6;
1444 }
1445 mptsas_set_rphy(ioc, phy_info, rphy);
1446 return 0;
1447}
1448
1449/**
fc847ab4 1450 * mptsas_del_end_device - report a deleted end device to sas transport layer
3eb0822c
KD
1451 * @ioc: Pointer to MPT_ADAPTER structure
1452 * @phy_info: decribes attached device
1453 *
1454 **/
1455static void
1456mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1457{
1458 struct sas_rphy *rphy;
1459 struct sas_port *port;
1460 struct mptsas_portinfo *port_info;
1461 struct mptsas_phyinfo *phy_info_parent;
1462 int i;
1463 char *ds = NULL;
1464 u8 fw_id;
1465 u64 sas_address;
1466
1467 if (!phy_info)
1468 return;
1469
1470 fw_id = phy_info->attached.id;
1471 sas_address = phy_info->attached.sas_address;
1472
1473 if (!phy_info->port_details) {
1474 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1475 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1476 __func__, fw_id, __LINE__));
1477 return;
1478 }
1479 rphy = mptsas_get_rphy(phy_info);
1480 if (!rphy) {
1481 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1482 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1483 __func__, fw_id, __LINE__));
1484 return;
1485 }
1486
1487 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1488 || phy_info->attached.device_info
1489 & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1490 || phy_info->attached.device_info
1491 & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1492 ds = "initiator";
1493 if (phy_info->attached.device_info &
1494 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1495 ds = "ssp";
1496 if (phy_info->attached.device_info &
1497 MPI_SAS_DEVICE_INFO_STP_TARGET)
1498 ds = "stp";
1499 if (phy_info->attached.device_info &
1500 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1501 ds = "sata";
1502
1503 dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1504 "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1505 "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1506 phy_info->attached.id, phy_info->attached.phy_id,
1507 (unsigned long long) sas_address);
1508
1509 port = mptsas_get_port(phy_info);
1510 if (!port) {
1511 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1512 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1513 __func__, fw_id, __LINE__));
1514 return;
1515 }
1516 port_info = phy_info->portinfo;
1517 phy_info_parent = port_info->phy_info;
1518 for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1519 if (!phy_info_parent->phy)
1520 continue;
1521 if (phy_info_parent->attached.sas_address !=
1522 sas_address)
1523 continue;
1524 dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1525 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1526 ioc->name, phy_info_parent->phy_id,
1527 phy_info_parent->phy);
1528 sas_port_delete_phy(port, phy_info_parent->phy);
1529 }
1530
1531 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1532 "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1533 port->port_identifier, (unsigned long long)sas_address);
1534 sas_port_delete(port);
1535 mptsas_set_port(ioc, phy_info, NULL);
1536 mptsas_port_delete(ioc, phy_info->port_details);
1537}
1538
1539struct mptsas_phyinfo *
1540mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1541 struct mptsas_devinfo *sas_device)
1542{
1543 struct mptsas_phyinfo *phy_info;
1544 struct mptsas_portinfo *port_info;
1545 int i;
1546
1547 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1548 sas_device->sas_address);
1549 if (!phy_info)
1550 goto out;
1551 port_info = phy_info->portinfo;
1552 if (!port_info)
1553 goto out;
1554 mutex_lock(&ioc->sas_topology_mutex);
1555 for (i = 0; i < port_info->num_phys; i++) {
1556 if (port_info->phy_info[i].attached.sas_address !=
1557 sas_device->sas_address)
1558 continue;
1559 port_info->phy_info[i].attached.channel = sas_device->channel;
1560 port_info->phy_info[i].attached.id = sas_device->id;
1561 port_info->phy_info[i].attached.sas_address =
1562 sas_device->sas_address;
1563 port_info->phy_info[i].attached.handle = sas_device->handle;
1564 port_info->phy_info[i].attached.handle_parent =
1565 sas_device->handle_parent;
1566 port_info->phy_info[i].attached.handle_enclosure =
1567 sas_device->handle_enclosure;
1568 }
1569 mutex_unlock(&ioc->sas_topology_mutex);
1570 out:
1571 return phy_info;
1572}
1573
1574/**
1575 * mptsas_firmware_event_work - work thread for processing fw events
1576 * @work: work queue payload containing info describing the event
1577 * Context: user
1578 *
1579 */
1580static void
1581mptsas_firmware_event_work(struct work_struct *work)
1582{
1583 struct fw_event_work *fw_event =
1584 container_of(work, struct fw_event_work, work.work);
1585 MPT_ADAPTER *ioc = fw_event->ioc;
1586
eedf92b9
KD
1587 /* special rescan topology handling */
1588 if (fw_event->event == -1) {
1589 if (ioc->in_rescan) {
1590 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1591 "%s: rescan ignored as it is in progress\n",
1592 ioc->name, __func__));
1593 return;
1594 }
1595 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1596 "reset\n", ioc->name, __func__));
1597 ioc->in_rescan = 1;
1598 mptsas_not_responding_devices(ioc);
1599 mptsas_scan_sas_topology(ioc);
1600 ioc->in_rescan = 0;
1601 mptsas_free_fw_event(ioc, fw_event);
1602 return;
1603 }
3eb0822c
KD
1604
1605 /* events handling turned off during host reset */
1606 if (ioc->fw_events_off) {
1607 mptsas_free_fw_event(ioc, fw_event);
1608 return;
1609 }
1610
1611 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1612 "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1613 (fw_event->event & 0xFF)));
1614
1615 switch (fw_event->event) {
1616 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1617 mptsas_send_sas_event(fw_event);
1618 break;
1619 case MPI_EVENT_INTEGRATED_RAID:
1620 mptsas_send_raid_event(fw_event);
1621 break;
1622 case MPI_EVENT_IR2:
1623 mptsas_send_ir2_event(fw_event);
1624 break;
1625 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1626 mptbase_sas_persist_operation(ioc,
1627 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1628 mptsas_free_fw_event(ioc, fw_event);
1629 break;
db7051b2
KD
1630 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1631 mptsas_broadcast_primative_work(fw_event);
1632 break;
f9c34022
KD
1633 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1634 mptsas_send_expander_event(fw_event);
1635 break;
1636 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1637 mptsas_send_link_status_event(fw_event);
1638 break;
57e98513
KD
1639 case MPI_EVENT_QUEUE_FULL:
1640 mptsas_handle_queue_full_event(fw_event);
1641 break;
3eb0822c
KD
1642 }
1643}
1644
1645
1646
f013db32
JB
1647static int
1648mptsas_slave_configure(struct scsi_device *sdev)
1649{
3eb0822c
KD
1650 struct Scsi_Host *host = sdev->host;
1651 MPT_SCSI_HOST *hd = shost_priv(host);
1652 MPT_ADAPTER *ioc = hd->ioc;
a7938b0b 1653 VirtDevice *vdevice = sdev->hostdata;
3c0c25b9 1654
a7938b0b
KD
1655 if (vdevice->vtarget->deleted) {
1656 sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
1657 vdevice->vtarget->deleted = 0;
1658 }
1659
1660 /*
1661 * RAID volumes placed beyond the last expected port.
1662 * Ignore sending sas mode pages in that case..
1663 */
1664 if (sdev->channel == MPTSAS_RAID_CHANNEL) {
1665 mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
e8bf3941 1666 goto out;
a7938b0b 1667 }
e8bf3941
JB
1668
1669 sas_read_port_mode_page(sdev);
f013db32 1670
3eb0822c
KD
1671 mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1672
e8bf3941 1673 out:
f013db32
JB
1674 return mptscsih_slave_configure(sdev);
1675}
1676
547f9a21
EM
1677static int
1678mptsas_target_alloc(struct scsi_target *starget)
1679{
1680 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1681 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21 1682 VirtTarget *vtarget;
793955f5 1683 u8 id, channel;
547f9a21
EM
1684 struct sas_rphy *rphy;
1685 struct mptsas_portinfo *p;
1686 int i;
e80b002b 1687 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
1688
1689 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
1690 if (!vtarget)
1691 return -ENOMEM;
1692
1693 vtarget->starget = starget;
e80b002b 1694 vtarget->ioc_id = ioc->id;
793955f5
EM
1695 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
1696 id = starget->id;
547f9a21
EM
1697 channel = 0;
1698
793955f5
EM
1699 /*
1700 * RAID volumes placed beyond the last expected port.
1701 */
1702 if (starget->channel == MPTSAS_RAID_CHANNEL) {
a7938b0b
KD
1703 if (!ioc->raid_data.pIocPg2) {
1704 kfree(vtarget);
1705 return -ENXIO;
1706 }
1707 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1708 if (id == ioc->raid_data.pIocPg2->
1709 RaidVolume[i].VolumeID) {
1710 channel = ioc->raid_data.pIocPg2->
1711 RaidVolume[i].VolumeBus;
1712 }
1713 }
1714 vtarget->raidVolume = 1;
547f9a21 1715 goto out;
793955f5 1716 }
547f9a21
EM
1717
1718 rphy = dev_to_rphy(starget->dev.parent);
e80b002b
EM
1719 mutex_lock(&ioc->sas_topology_mutex);
1720 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1721 for (i = 0; i < p->num_phys; i++) {
1722 if (p->phy_info[i].attached.sas_address !=
1723 rphy->identify.sas_address)
1724 continue;
793955f5 1725 id = p->phy_info[i].attached.id;
547f9a21
EM
1726 channel = p->phy_info[i].attached.channel;
1727 mptsas_set_starget(&p->phy_info[i], starget);
1728
1729 /*
1730 * Exposing hidden raid components
1731 */
e80b002b
EM
1732 if (mptscsih_is_phys_disk(ioc, channel, id)) {
1733 id = mptscsih_raid_id_to_num(ioc,
793955f5 1734 channel, id);
547f9a21
EM
1735 vtarget->tflags |=
1736 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 1737 p->phy_info[i].attached.phys_disk_num = id;
547f9a21 1738 }
e80b002b 1739 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1740 goto out;
1741 }
1742 }
e80b002b 1743 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1744
1745 kfree(vtarget);
1746 return -ENXIO;
1747
1748 out:
793955f5
EM
1749 vtarget->id = id;
1750 vtarget->channel = channel;
547f9a21
EM
1751 starget->hostdata = vtarget;
1752 return 0;
1753}
1754
1755static void
1756mptsas_target_destroy(struct scsi_target *starget)
1757{
1758 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1759 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21
EM
1760 struct sas_rphy *rphy;
1761 struct mptsas_portinfo *p;
1762 int i;
3eb0822c
KD
1763 MPT_ADAPTER *ioc = hd->ioc;
1764 VirtTarget *vtarget;
547f9a21
EM
1765
1766 if (!starget->hostdata)
1767 return;
1768
3eb0822c
KD
1769 vtarget = starget->hostdata;
1770
57e98513
KD
1771 mptsas_del_device_component_by_os(ioc, starget->channel,
1772 starget->id);
1773
3eb0822c 1774
e8bf3941 1775 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
1776 goto out;
1777
1778 rphy = dev_to_rphy(starget->dev.parent);
e80b002b 1779 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1780 for (i = 0; i < p->num_phys; i++) {
1781 if (p->phy_info[i].attached.sas_address !=
1782 rphy->identify.sas_address)
1783 continue;
3eb0822c
KD
1784
1785 starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1786 "delete device: fw_channel %d, fw_id %d, phy %d, "
1787 "sas_addr 0x%llx\n", ioc->name,
1788 p->phy_info[i].attached.channel,
1789 p->phy_info[i].attached.id,
1790 p->phy_info[i].attached.phy_id, (unsigned long long)
1791 p->phy_info[i].attached.sas_address);
1792
547f9a21 1793 mptsas_set_starget(&p->phy_info[i], NULL);
547f9a21
EM
1794 }
1795 }
1796
1797 out:
3eb0822c 1798 vtarget->starget = NULL;
547f9a21
EM
1799 kfree(starget->hostdata);
1800 starget->hostdata = NULL;
1801}
1802
1803
0c33b27d 1804static int
c7c82987 1805mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 1806{
c7c82987 1807 struct Scsi_Host *host = sdev->host;
e7eae9f6 1808 MPT_SCSI_HOST *hd = shost_priv(host);
0c33b27d
CH
1809 struct sas_rphy *rphy;
1810 struct mptsas_portinfo *p;
a69de507 1811 VirtDevice *vdevice;
c7c82987 1812 struct scsi_target *starget;
547f9a21 1813 int i;
e80b002b 1814 MPT_ADAPTER *ioc = hd->ioc;
0c33b27d 1815
a69de507
EM
1816 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1817 if (!vdevice) {
547f9a21 1818 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
e80b002b 1819 ioc->name, sizeof(VirtDevice));
0c33b27d
CH
1820 return -ENOMEM;
1821 }
c7c82987 1822 starget = scsi_target(sdev);
a69de507 1823 vdevice->vtarget = starget->hostdata;
0c33b27d 1824
e8bf3941 1825 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 1826 goto out;
816aa907 1827
c7c82987 1828 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
e80b002b
EM
1829 mutex_lock(&ioc->sas_topology_mutex);
1830 list_for_each_entry(p, &ioc->sas_topology, list) {
0c33b27d 1831 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
1832 if (p->phy_info[i].attached.sas_address !=
1833 rphy->identify.sas_address)
1834 continue;
a69de507 1835 vdevice->lun = sdev->lun;
547f9a21
EM
1836 /*
1837 * Exposing hidden raid components
1838 */
e80b002b 1839 if (mptscsih_is_phys_disk(ioc,
793955f5
EM
1840 p->phy_info[i].attached.channel,
1841 p->phy_info[i].attached.id))
547f9a21 1842 sdev->no_uld_attach = 1;
e80b002b 1843 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21 1844 goto out;
0c33b27d
CH
1845 }
1846 }
e80b002b 1847 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 1848
a69de507 1849 kfree(vdevice);
23f236ed 1850 return -ENXIO;
0c33b27d
CH
1851
1852 out:
a69de507
EM
1853 vdevice->vtarget->num_luns++;
1854 sdev->hostdata = vdevice;
0c33b27d
CH
1855 return 0;
1856}
1857
547f9a21
EM
1858static int
1859mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 1860{
7b5a65b9
KD
1861 MPT_SCSI_HOST *hd;
1862 MPT_ADAPTER *ioc;
a69de507 1863 VirtDevice *vdevice = SCpnt->device->hostdata;
7d3eecf7 1864
a69de507 1865 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
547f9a21
EM
1866 SCpnt->result = DID_NO_CONNECT << 16;
1867 done(SCpnt);
1868 return 0;
7d3eecf7 1869 }
547f9a21 1870
7b5a65b9
KD
1871 hd = shost_priv(SCpnt->device->host);
1872 ioc = hd->ioc;
1873
1874 if (ioc->sas_discovery_quiesce_io)
1875 return SCSI_MLQUEUE_HOST_BUSY;
1876
793955f5
EM
1877// scsi_print_command(SCpnt);
1878
547f9a21 1879 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1880}
1881
547f9a21 1882
0c33b27d 1883static struct scsi_host_template mptsas_driver_template = {
f78496da 1884 .module = THIS_MODULE,
0c33b27d
CH
1885 .proc_name = "mptsas",
1886 .proc_info = mptscsih_proc_info,
1887 .name = "MPT SPI Host",
1888 .info = mptscsih_info,
547f9a21
EM
1889 .queuecommand = mptsas_qcmd,
1890 .target_alloc = mptsas_target_alloc,
0c33b27d 1891 .slave_alloc = mptsas_slave_alloc,
f013db32 1892 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1893 .target_destroy = mptsas_target_destroy,
1894 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1895 .change_queue_depth = mptscsih_change_queue_depth,
1896 .eh_abort_handler = mptscsih_abort,
1897 .eh_device_reset_handler = mptscsih_dev_reset,
1898 .eh_bus_reset_handler = mptscsih_bus_reset,
1899 .eh_host_reset_handler = mptscsih_host_reset,
1900 .bios_param = mptscsih_bios_param,
9d2e9d66 1901 .can_queue = MPT_SAS_CAN_QUEUE,
0c33b27d
CH
1902 .this_id = -1,
1903 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1904 .max_sectors = 8192,
1905 .cmd_per_lun = 7,
1906 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1907 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1908};
1909
b5141128 1910static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1911{
b5141128
CH
1912 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1913 ConfigExtendedPageHeader_t hdr;
1914 CONFIGPARMS cfg;
1915 SasPhyPage1_t *buffer;
1916 dma_addr_t dma_handle;
1917 int error;
0c33b27d 1918
f4ad7b58
JB
1919 /* FIXME: only have link errors on local phys */
1920 if (!scsi_is_sas_phy_local(phy))
1921 return -EINVAL;
1922
b5141128
CH
1923 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1924 hdr.ExtPageLength = 0;
1925 hdr.PageNumber = 1 /* page number 1*/;
1926 hdr.Reserved1 = 0;
1927 hdr.Reserved2 = 0;
1928 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1929 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 1930
b5141128
CH
1931 cfg.cfghdr.ehdr = &hdr;
1932 cfg.physAddr = -1;
1933 cfg.pageAddr = phy->identify.phy_identifier;
1934 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1935 cfg.dir = 0; /* read */
4b97650b 1936 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d 1937
b5141128
CH
1938 error = mpt_config(ioc, &cfg);
1939 if (error)
1940 return error;
1941 if (!hdr.ExtPageLength)
1942 return -ENXIO;
0c33b27d 1943
b5141128
CH
1944 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1945 &dma_handle);
1946 if (!buffer)
1947 return -ENOMEM;
0c33b27d 1948
b5141128
CH
1949 cfg.physAddr = dma_handle;
1950 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1951
1952 error = mpt_config(ioc, &cfg);
1953 if (error)
1954 goto out_free_consistent;
1955
d6ecdd63 1956 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
1957
1958 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1959 phy->running_disparity_error_count =
1960 le32_to_cpu(buffer->RunningDisparityErrorCount);
1961 phy->loss_of_dword_sync_count =
1962 le32_to_cpu(buffer->LossDwordSynchCount);
1963 phy->phy_reset_problem_count =
1964 le32_to_cpu(buffer->PhyResetProblemCount);
1965
1966 out_free_consistent:
1967 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1968 buffer, dma_handle);
1969 return error;
0c33b27d
CH
1970}
1971
da4fa655
CH
1972static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1973 MPT_FRAME_HDR *reply)
1974{
f0f09d3b 1975 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
da4fa655 1976 if (reply != NULL) {
f0f09d3b 1977 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
da4fa655
CH
1978 memcpy(ioc->sas_mgmt.reply, reply,
1979 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1980 }
2f187862
KD
1981
1982 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1983 ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
1984 complete(&ioc->sas_mgmt.done);
1985 return 1;
1986 }
1987 return 0;
da4fa655
CH
1988}
1989
1990static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1991{
1992 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1993 SasIoUnitControlRequest_t *req;
1994 SasIoUnitControlReply_t *reply;
1995 MPT_FRAME_HDR *mf;
1996 MPIHeader_t *hdr;
1997 unsigned long timeleft;
1998 int error = -ERESTARTSYS;
1999
f4ad7b58
JB
2000 /* FIXME: fusion doesn't allow non-local phy reset */
2001 if (!scsi_is_sas_phy_local(phy))
2002 return -EINVAL;
2003
da4fa655
CH
2004 /* not implemented for expanders */
2005 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
2006 return -ENXIO;
2007
eeb846ce 2008 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
2009 goto out;
2010
2011 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2012 if (!mf) {
2013 error = -ENOMEM;
2014 goto out_unlock;
2015 }
2016
2017 hdr = (MPIHeader_t *) mf;
2018 req = (SasIoUnitControlRequest_t *)mf;
2019 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
2020 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2021 req->MsgContext = hdr->MsgContext;
2022 req->Operation = hard_reset ?
2023 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
2024 req->PhyNum = phy->identify.phy_identifier;
2025
2f187862 2026 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
da4fa655
CH
2027 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2028
2029 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
2030 10 * HZ);
2031 if (!timeleft) {
2032 /* On timeout reset the board */
2033 mpt_free_msg_frame(ioc, mf);
2034 mpt_HardResetHandler(ioc, CAN_SLEEP);
2035 error = -ETIMEDOUT;
2036 goto out_unlock;
2037 }
2038
2039 /* a reply frame is expected */
2040 if ((ioc->sas_mgmt.status &
f0f09d3b 2041 MPT_MGMT_STATUS_RF_VALID) == 0) {
da4fa655
CH
2042 error = -ENXIO;
2043 goto out_unlock;
2044 }
2045
2046 /* process the completed Reply Message Frame */
2047 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
2048 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
29dd3609 2049 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
cadbd4a5 2050 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
da4fa655
CH
2051 error = -ENXIO;
2052 goto out_unlock;
2053 }
2054
2055 error = 0;
2056
2057 out_unlock:
2f187862 2058 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
eeb846ce 2059 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
2060 out:
2061 return error;
2062}
0c33b27d 2063
e3094447
CH
2064static int
2065mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
2066{
2067 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2068 int i, error;
2069 struct mptsas_portinfo *p;
2070 struct mptsas_enclosure enclosure_info;
2071 u64 enclosure_handle;
2072
2073 mutex_lock(&ioc->sas_topology_mutex);
2074 list_for_each_entry(p, &ioc->sas_topology, list) {
2075 for (i = 0; i < p->num_phys; i++) {
2076 if (p->phy_info[i].attached.sas_address ==
2077 rphy->identify.sas_address) {
2078 enclosure_handle = p->phy_info[i].
2079 attached.handle_enclosure;
2080 goto found_info;
2081 }
2082 }
2083 }
2084 mutex_unlock(&ioc->sas_topology_mutex);
2085 return -ENXIO;
2086
2087 found_info:
2088 mutex_unlock(&ioc->sas_topology_mutex);
2089 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 2090 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
2091 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
2092 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
2093 if (!error)
2094 *identifier = enclosure_info.enclosure_logical_id;
2095 return error;
2096}
2097
2098static int
2099mptsas_get_bay_identifier(struct sas_rphy *rphy)
2100{
2101 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2102 struct mptsas_portinfo *p;
2103 int i, rc;
2104
2105 mutex_lock(&ioc->sas_topology_mutex);
2106 list_for_each_entry(p, &ioc->sas_topology, list) {
2107 for (i = 0; i < p->num_phys; i++) {
2108 if (p->phy_info[i].attached.sas_address ==
2109 rphy->identify.sas_address) {
2110 rc = p->phy_info[i].attached.slot;
2111 goto out;
2112 }
2113 }
2114 }
2115 rc = -ENXIO;
2116 out:
2117 mutex_unlock(&ioc->sas_topology_mutex);
2118 return rc;
2119}
2120
159e36fe
FT
2121static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2122 struct request *req)
2123{
2124 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
2125 MPT_FRAME_HDR *mf;
2126 SmpPassthroughRequest_t *smpreq;
2127 struct request *rsp = req->next_rq;
2128 int ret;
2129 int flagsLength;
2130 unsigned long timeleft;
2131 char *psge;
2132 dma_addr_t dma_addr_in = 0;
2133 dma_addr_t dma_addr_out = 0;
2134 u64 sas_address = 0;
2135
2136 if (!rsp) {
29dd3609 2137 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
cadbd4a5 2138 ioc->name, __func__);
159e36fe
FT
2139 return -EINVAL;
2140 }
2141
2142 /* do we need to support multiple segments? */
2143 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
29dd3609 2144 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
b0790410
TH
2145 ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
2146 rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
159e36fe
FT
2147 return -EINVAL;
2148 }
2149
2150 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2151 if (ret)
2152 goto out;
2153
2154 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2155 if (!mf) {
2156 ret = -ENOMEM;
2157 goto out_unlock;
2158 }
2159
2160 smpreq = (SmpPassthroughRequest_t *)mf;
2161 memset(smpreq, 0, sizeof(*smpreq));
2162
b0790410 2163 smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
159e36fe
FT
2164 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2165
2166 if (rphy)
2167 sas_address = rphy->identify.sas_address;
2168 else {
2169 struct mptsas_portinfo *port_info;
2170
2171 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 2172 port_info = ioc->hba_port_info;
159e36fe
FT
2173 if (port_info && port_info->phy_info)
2174 sas_address =
2175 port_info->phy_info[0].phy->identify.sas_address;
2176 mutex_unlock(&ioc->sas_topology_mutex);
2177 }
2178
2179 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2180
2181 psge = (char *)
2182 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2183
2184 /* request */
2185 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2186 MPI_SGE_FLAGS_END_OF_BUFFER |
14d0f0b0
KD
2187 MPI_SGE_FLAGS_DIRECTION)
2188 << MPI_SGE_FLAGS_SHIFT;
b0790410 2189 flagsLength |= (blk_rq_bytes(req) - 4);
159e36fe
FT
2190
2191 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
b0790410 2192 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
159e36fe
FT
2193 if (!dma_addr_out)
2194 goto put_mf;
14d0f0b0 2195 ioc->add_sge(psge, flagsLength, dma_addr_out);
2f187862 2196 psge += ioc->SGE_size;
159e36fe
FT
2197
2198 /* response */
2f187862
KD
2199 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2200 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2201 MPI_SGE_FLAGS_IOC_TO_HOST |
2202 MPI_SGE_FLAGS_END_OF_BUFFER;
2203
2204 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
b0790410 2205 flagsLength |= blk_rq_bytes(rsp) + 4;
159e36fe 2206 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
b0790410 2207 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
159e36fe
FT
2208 if (!dma_addr_in)
2209 goto unmap;
14d0f0b0 2210 ioc->add_sge(psge, flagsLength, dma_addr_in);
159e36fe 2211
2f187862 2212 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
159e36fe
FT
2213 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2214
2215 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2216 if (!timeleft) {
cadbd4a5 2217 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
159e36fe
FT
2218 /* On timeout reset the board */
2219 mpt_HardResetHandler(ioc, CAN_SLEEP);
2220 ret = -ETIMEDOUT;
2221 goto unmap;
2222 }
2223 mf = NULL;
2224
f0f09d3b 2225 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
159e36fe
FT
2226 SmpPassthroughReply_t *smprep;
2227
2228 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2229 memcpy(req->sense, smprep, sizeof(*smprep));
2230 req->sense_len = sizeof(*smprep);
5f49f631
TH
2231 req->resid_len = 0;
2232 rsp->resid_len -= smprep->ResponseDataLength;
159e36fe 2233 } else {
2f187862
KD
2234 printk(MYIOC_s_ERR_FMT
2235 "%s: smp passthru reply failed to be returned\n",
cadbd4a5 2236 ioc->name, __func__);
159e36fe
FT
2237 ret = -ENXIO;
2238 }
2239unmap:
2240 if (dma_addr_out)
b0790410 2241 pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
159e36fe
FT
2242 PCI_DMA_BIDIRECTIONAL);
2243 if (dma_addr_in)
b0790410 2244 pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
159e36fe
FT
2245 PCI_DMA_BIDIRECTIONAL);
2246put_mf:
2247 if (mf)
2248 mpt_free_msg_frame(ioc, mf);
2249out_unlock:
2f187862 2250 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
159e36fe
FT
2251 mutex_unlock(&ioc->sas_mgmt.mutex);
2252out:
2253 return ret;
2254}
2255
b5141128
CH
2256static struct sas_function_template mptsas_transport_functions = {
2257 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
2258 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2259 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 2260 .phy_reset = mptsas_phy_reset,
159e36fe 2261 .smp_handler = mptsas_smp_handler,
b5141128
CH
2262};
2263
2264static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
2265
2266static int
2267mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2268{
2269 ConfigExtendedPageHeader_t hdr;
2270 CONFIGPARMS cfg;
2271 SasIOUnitPage0_t *buffer;
2272 dma_addr_t dma_handle;
2273 int error, i;
2274
2275 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2276 hdr.ExtPageLength = 0;
2277 hdr.PageNumber = 0;
2278 hdr.Reserved1 = 0;
2279 hdr.Reserved2 = 0;
2280 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2281 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2282
2283 cfg.cfghdr.ehdr = &hdr;
2284 cfg.physAddr = -1;
2285 cfg.pageAddr = 0;
2286 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2287 cfg.dir = 0; /* read */
4b97650b 2288 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d
CH
2289
2290 error = mpt_config(ioc, &cfg);
2291 if (error)
2292 goto out;
2293 if (!hdr.ExtPageLength) {
2294 error = -ENXIO;
2295 goto out;
2296 }
2297
2298 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2299 &dma_handle);
2300 if (!buffer) {
2301 error = -ENOMEM;
2302 goto out;
2303 }
2304
2305 cfg.physAddr = dma_handle;
2306 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2307
2308 error = mpt_config(ioc, &cfg);
2309 if (error)
2310 goto out_free_consistent;
2311
2312 port_info->num_phys = buffer->NumPhys;
2313 port_info->phy_info = kcalloc(port_info->num_phys,
2f187862 2314 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
0c33b27d
CH
2315 if (!port_info->phy_info) {
2316 error = -ENOMEM;
2317 goto out_free_consistent;
2318 }
2319
edb9068d
PS
2320 ioc->nvdata_version_persistent =
2321 le16_to_cpu(buffer->NvdataVersionPersistent);
2322 ioc->nvdata_version_default =
2323 le16_to_cpu(buffer->NvdataVersionDefault);
2324
0c33b27d 2325 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 2326 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
2327 port_info->phy_info[i].phy_id = i;
2328 port_info->phy_info[i].port_id =
2329 buffer->PhyData[i].Port;
2330 port_info->phy_info[i].negotiated_link_rate =
2331 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 2332 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2333 port_info->phy_info[i].handle =
2334 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
2335 }
2336
2337 out_free_consistent:
2338 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2339 buffer, dma_handle);
2340 out:
2341 return error;
2342}
2343
edb9068d
PS
2344static int
2345mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2346{
2347 ConfigExtendedPageHeader_t hdr;
2348 CONFIGPARMS cfg;
2349 SasIOUnitPage1_t *buffer;
2350 dma_addr_t dma_handle;
2351 int error;
2352 u16 device_missing_delay;
2353
2354 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2355 memset(&cfg, 0, sizeof(CONFIGPARMS));
2356
2357 cfg.cfghdr.ehdr = &hdr;
2358 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4b97650b 2359 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
edb9068d
PS
2360 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2361 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2362 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2363 cfg.cfghdr.ehdr->PageNumber = 1;
2364
2365 error = mpt_config(ioc, &cfg);
2366 if (error)
2367 goto out;
2368 if (!hdr.ExtPageLength) {
2369 error = -ENXIO;
2370 goto out;
2371 }
2372
2373 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2374 &dma_handle);
2375 if (!buffer) {
2376 error = -ENOMEM;
2377 goto out;
2378 }
2379
2380 cfg.physAddr = dma_handle;
2381 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2382
2383 error = mpt_config(ioc, &cfg);
2384 if (error)
2385 goto out_free_consistent;
2386
2387 ioc->io_missing_delay =
2388 le16_to_cpu(buffer->IODeviceMissingDelay);
2389 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
2390 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2391 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2392 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2393
2394 out_free_consistent:
2395 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2396 buffer, dma_handle);
2397 out:
2398 return error;
2399}
2400
0c33b27d
CH
2401static int
2402mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2403 u32 form, u32 form_specific)
2404{
2405 ConfigExtendedPageHeader_t hdr;
2406 CONFIGPARMS cfg;
2407 SasPhyPage0_t *buffer;
2408 dma_addr_t dma_handle;
2409 int error;
2410
2411 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2412 hdr.ExtPageLength = 0;
2413 hdr.PageNumber = 0;
2414 hdr.Reserved1 = 0;
2415 hdr.Reserved2 = 0;
2416 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2417 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2418
2419 cfg.cfghdr.ehdr = &hdr;
2420 cfg.dir = 0; /* read */
4b97650b 2421 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d
CH
2422
2423 /* Get Phy Pg 0 for each Phy. */
2424 cfg.physAddr = -1;
2425 cfg.pageAddr = form + form_specific;
2426 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2427
2428 error = mpt_config(ioc, &cfg);
2429 if (error)
2430 goto out;
2431
2432 if (!hdr.ExtPageLength) {
2433 error = -ENXIO;
2434 goto out;
2435 }
2436
2437 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2438 &dma_handle);
2439 if (!buffer) {
2440 error = -ENOMEM;
2441 goto out;
2442 }
2443
2444 cfg.physAddr = dma_handle;
2445 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2446
2447 error = mpt_config(ioc, &cfg);
2448 if (error)
2449 goto out_free_consistent;
2450
d6ecdd63 2451 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
2452
2453 phy_info->hw_link_rate = buffer->HwLinkRate;
2454 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2455 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2456 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2457
2458 out_free_consistent:
2459 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2460 buffer, dma_handle);
2461 out:
2462 return error;
2463}
2464
2465static int
2466mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2467 u32 form, u32 form_specific)
2468{
2469 ConfigExtendedPageHeader_t hdr;
2470 CONFIGPARMS cfg;
2471 SasDevicePage0_t *buffer;
2472 dma_addr_t dma_handle;
2473 __le64 sas_address;
bd23e94c
ME
2474 int error=0;
2475
0c33b27d
CH
2476 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2477 hdr.ExtPageLength = 0;
2478 hdr.PageNumber = 0;
2479 hdr.Reserved1 = 0;
2480 hdr.Reserved2 = 0;
2481 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2482 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2483
2484 cfg.cfghdr.ehdr = &hdr;
2485 cfg.pageAddr = form + form_specific;
2486 cfg.physAddr = -1;
2487 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2488 cfg.dir = 0; /* read */
4b97650b 2489 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d 2490
db9c9174 2491 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
2492 error = mpt_config(ioc, &cfg);
2493 if (error)
2494 goto out;
2495 if (!hdr.ExtPageLength) {
2496 error = -ENXIO;
2497 goto out;
2498 }
2499
2500 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2501 &dma_handle);
2502 if (!buffer) {
2503 error = -ENOMEM;
2504 goto out;
2505 }
2506
2507 cfg.physAddr = dma_handle;
2508 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2509
2510 error = mpt_config(ioc, &cfg);
2511 if (error)
2512 goto out_free_consistent;
2513
d6ecdd63 2514 mptsas_print_device_pg0(ioc, buffer);
0c33b27d 2515
2f187862 2516 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d 2517 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 2518 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
2519 device_info->handle_enclosure =
2520 le16_to_cpu(buffer->EnclosureHandle);
2521 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
2522 device_info->phy_id = buffer->PhyNum;
2523 device_info->port_id = buffer->PhysicalPort;
9a28f49a 2524 device_info->id = buffer->TargetID;
b506ade9 2525 device_info->phys_disk_num = ~0;
9a28f49a 2526 device_info->channel = buffer->Bus;
0c33b27d
CH
2527 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2528 device_info->sas_address = le64_to_cpu(sas_address);
2529 device_info->device_info =
2530 le32_to_cpu(buffer->DeviceInfo);
2531
2532 out_free_consistent:
2533 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2534 buffer, dma_handle);
2535 out:
2536 return error;
2537}
2538
2539static int
2540mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2541 u32 form, u32 form_specific)
2542{
2543 ConfigExtendedPageHeader_t hdr;
2544 CONFIGPARMS cfg;
2545 SasExpanderPage0_t *buffer;
2546 dma_addr_t dma_handle;
547f9a21 2547 int i, error;
2f187862 2548 __le64 sas_address;
0c33b27d 2549
2f187862 2550 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2551 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2552 hdr.ExtPageLength = 0;
2553 hdr.PageNumber = 0;
2554 hdr.Reserved1 = 0;
2555 hdr.Reserved2 = 0;
2556 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2557 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2558
2559 cfg.cfghdr.ehdr = &hdr;
2560 cfg.physAddr = -1;
2561 cfg.pageAddr = form + form_specific;
2562 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2563 cfg.dir = 0; /* read */
4b97650b 2564 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d 2565
db9c9174 2566 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2567 error = mpt_config(ioc, &cfg);
2568 if (error)
2569 goto out;
2570
2571 if (!hdr.ExtPageLength) {
2572 error = -ENXIO;
2573 goto out;
2574 }
2575
2576 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2577 &dma_handle);
2578 if (!buffer) {
2579 error = -ENOMEM;
2580 goto out;
2581 }
2582
2583 cfg.physAddr = dma_handle;
2584 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2585
2586 error = mpt_config(ioc, &cfg);
2587 if (error)
2588 goto out_free_consistent;
2589
51f39eae
KO
2590 if (!buffer->NumPhys) {
2591 error = -ENODEV;
2592 goto out_free_consistent;
2593 }
2594
0c33b27d 2595 /* save config data */
2f187862 2596 port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
0c33b27d 2597 port_info->phy_info = kcalloc(port_info->num_phys,
2f187862 2598 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
0c33b27d
CH
2599 if (!port_info->phy_info) {
2600 error = -ENOMEM;
2601 goto out_free_consistent;
2602 }
2603
2f187862 2604 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2ecce492 2605 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 2606 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2607 port_info->phy_info[i].handle =
2608 le16_to_cpu(buffer->DevHandle);
2f187862
KD
2609 port_info->phy_info[i].identify.sas_address =
2610 le64_to_cpu(sas_address);
2611 port_info->phy_info[i].identify.handle_parent =
2612 le16_to_cpu(buffer->ParentDevHandle);
2ecce492 2613 }
547f9a21 2614
0c33b27d
CH
2615 out_free_consistent:
2616 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2617 buffer, dma_handle);
2618 out:
2619 return error;
2620}
2621
2622static int
2623mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2624 u32 form, u32 form_specific)
2625{
2626 ConfigExtendedPageHeader_t hdr;
2627 CONFIGPARMS cfg;
2628 SasExpanderPage1_t *buffer;
2629 dma_addr_t dma_handle;
bd23e94c
ME
2630 int error=0;
2631
2f187862 2632 hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
0c33b27d
CH
2633 hdr.ExtPageLength = 0;
2634 hdr.PageNumber = 1;
2635 hdr.Reserved1 = 0;
2636 hdr.Reserved2 = 0;
2637 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2638 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2639
2640 cfg.cfghdr.ehdr = &hdr;
2641 cfg.physAddr = -1;
2642 cfg.pageAddr = form + form_specific;
2643 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2644 cfg.dir = 0; /* read */
4b97650b 2645 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d
CH
2646
2647 error = mpt_config(ioc, &cfg);
2648 if (error)
2649 goto out;
2650
2651 if (!hdr.ExtPageLength) {
2652 error = -ENXIO;
2653 goto out;
2654 }
2655
2656 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2657 &dma_handle);
2658 if (!buffer) {
2659 error = -ENOMEM;
2660 goto out;
2661 }
2662
2663 cfg.physAddr = dma_handle;
2664 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2665
2666 error = mpt_config(ioc, &cfg);
2f187862
KD
2667
2668 if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2669 error = -ENODEV;
2670 goto out;
2671 }
2672
0c33b27d
CH
2673 if (error)
2674 goto out_free_consistent;
2675
2676
d6ecdd63 2677 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
2678
2679 /* save config data */
024358ee 2680 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
2681 phy_info->port_id = buffer->PhysicalPort;
2682 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2683 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2684 phy_info->hw_link_rate = buffer->HwLinkRate;
2685 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2686 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2687
0c33b27d
CH
2688 out_free_consistent:
2689 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2690 buffer, dma_handle);
2691 out:
2692 return error;
2693}
2694
2695static void
2696mptsas_parse_device_info(struct sas_identify *identify,
2697 struct mptsas_devinfo *device_info)
2698{
2699 u16 protocols;
2700
2701 identify->sas_address = device_info->sas_address;
2702 identify->phy_identifier = device_info->phy_id;
2703
2704 /*
2705 * Fill in Phy Initiator Port Protocol.
2706 * Bits 6:3, more than one bit can be set, fall through cases.
2707 */
2708 protocols = device_info->device_info & 0x78;
2709 identify->initiator_port_protocols = 0;
2710 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
2711 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
2712 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
2713 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
2714 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
2715 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
2716 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
2717 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
2718
2719 /*
2720 * Fill in Phy Target Port Protocol.
2721 * Bits 10:7, more than one bit can be set, fall through cases.
2722 */
2723 protocols = device_info->device_info & 0x780;
2724 identify->target_port_protocols = 0;
2725 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2726 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
2727 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
2728 identify->target_port_protocols |= SAS_PROTOCOL_STP;
2729 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
2730 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
2731 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2732 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
2733
2734 /*
2735 * Fill in Attached device type.
2736 */
2737 switch (device_info->device_info &
2738 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
2739 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
2740 identify->device_type = SAS_PHY_UNUSED;
2741 break;
2742 case MPI_SAS_DEVICE_INFO_END_DEVICE:
2743 identify->device_type = SAS_END_DEVICE;
2744 break;
2745 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
2746 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
2747 break;
2748 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
2749 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
2750 break;
2751 }
2752}
2753
2754static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 2755 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 2756{
e6b2d76a 2757 MPT_ADAPTER *ioc;
9a28f49a 2758 struct sas_phy *phy;
547f9a21
EM
2759 struct sas_port *port;
2760 int error = 0;
0c33b27d 2761
547f9a21
EM
2762 if (!dev) {
2763 error = -ENODEV;
2764 goto out;
2765 }
e6b2d76a
ME
2766
2767 if (!phy_info->phy) {
2768 phy = sas_phy_alloc(dev, index);
547f9a21
EM
2769 if (!phy) {
2770 error = -ENOMEM;
2771 goto out;
2772 }
e6b2d76a
ME
2773 } else
2774 phy = phy_info->phy;
0c33b27d 2775
9a28f49a 2776 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
2777
2778 /*
2779 * Set Negotiated link rate.
2780 */
2781 switch (phy_info->negotiated_link_rate) {
2782 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 2783 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
2784 break;
2785 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 2786 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
2787 break;
2788 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 2789 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2790 break;
2791 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 2792 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2793 break;
2794 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
2795 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
2796 default:
9a28f49a 2797 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
2798 break;
2799 }
2800
2801 /*
2802 * Set Max hardware link rate.
2803 */
2804 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2805 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 2806 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2807 break;
2808 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 2809 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2810 break;
2811 default:
2812 break;
2813 }
2814
2815 /*
2816 * Set Max programmed link rate.
2817 */
2818 switch (phy_info->programmed_link_rate &
2819 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2820 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 2821 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2822 break;
2823 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 2824 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2825 break;
2826 default:
2827 break;
2828 }
2829
2830 /*
2831 * Set Min hardware link rate.
2832 */
2833 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
2834 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 2835 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2836 break;
2837 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2838 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2839 break;
2840 default:
2841 break;
2842 }
2843
2844 /*
2845 * Set Min programmed link rate.
2846 */
2847 switch (phy_info->programmed_link_rate &
2848 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
2849 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 2850 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2851 break;
2852 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2853 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2854 break;
2855 default:
2856 break;
2857 }
2858
e6b2d76a 2859 if (!phy_info->phy) {
ac01bbbd 2860
e6b2d76a
ME
2861 error = sas_phy_add(phy);
2862 if (error) {
2863 sas_phy_free(phy);
547f9a21 2864 goto out;
e6b2d76a
ME
2865 }
2866 phy_info->phy = phy;
0c33b27d
CH
2867 }
2868
547f9a21
EM
2869 if (!phy_info->attached.handle ||
2870 !phy_info->port_details)
2871 goto out;
2872
2873 port = mptsas_get_port(phy_info);
2874 ioc = phy_to_ioc(phy_info->phy);
2875
2876 if (phy_info->sas_port_add_phy) {
2877
2878 if (!port) {
dc22f16d 2879 port = sas_port_alloc_num(dev);
547f9a21
EM
2880 if (!port) {
2881 error = -ENOMEM;
2882 goto out;
2883 }
2884 error = sas_port_add(port);
2885 if (error) {
d6ecdd63 2886 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2887 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2888 __func__, __LINE__));
547f9a21
EM
2889 goto out;
2890 }
d6ecdd63 2891 mptsas_set_port(ioc, phy_info, port);
2f187862
KD
2892 devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
2893 MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
2894 ioc->name, port->port_identifier,
2895 (unsigned long long)phy_info->
2896 attached.sas_address));
547f9a21 2897 }
2f187862
KD
2898 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2899 "sas_port_add_phy: phy_id=%d\n",
2900 ioc->name, phy_info->phy_id));
547f9a21
EM
2901 sas_port_add_phy(port, phy_info->phy);
2902 phy_info->sas_port_add_phy = 0;
2f187862
KD
2903 devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
2904 MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
2905 phy_info->phy_id, phy_info->phy));
547f9a21 2906 }
547f9a21 2907 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 2908
0c33b27d 2909 struct sas_rphy *rphy;
2686de27 2910 struct device *parent;
f013db32 2911 struct sas_identify identify;
0c33b27d 2912
2686de27 2913 parent = dev->parent->parent;
e6b2d76a
ME
2914 /*
2915 * Let the hotplug_work thread handle processing
2916 * the adding/removing of devices that occur
2917 * after start of day.
2918 */
2f187862
KD
2919 if (mptsas_is_end_device(&phy_info->attached) &&
2920 phy_info->attached.handle_parent) {
2921 goto out;
2922 }
e6b2d76a 2923
f013db32 2924 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
2925 if (scsi_is_host_device(parent)) {
2926 struct mptsas_portinfo *port_info;
2927 int i;
2928
f9c34022 2929 port_info = ioc->hba_port_info;
2686de27
JB
2930
2931 for (i = 0; i < port_info->num_phys; i++)
2932 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
2933 identify.sas_address) {
2934 sas_port_mark_backlink(port);
2686de27 2935 goto out;
0c269e6d 2936 }
2686de27
JB
2937
2938 } else if (scsi_is_sas_rphy(parent)) {
2939 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2940 if (identify.sas_address ==
0c269e6d
JB
2941 parent_rphy->identify.sas_address) {
2942 sas_port_mark_backlink(port);
2686de27 2943 goto out;
0c269e6d 2944 }
2686de27
JB
2945 }
2946
f013db32
JB
2947 switch (identify.device_type) {
2948 case SAS_END_DEVICE:
547f9a21 2949 rphy = sas_end_device_alloc(port);
f013db32
JB
2950 break;
2951 case SAS_EDGE_EXPANDER_DEVICE:
2952 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 2953 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
2954 break;
2955 default:
2956 rphy = NULL;
2957 break;
2958 }
547f9a21 2959 if (!rphy) {
d6ecdd63 2960 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2961 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2962 __func__, __LINE__));
547f9a21
EM
2963 goto out;
2964 }
0c33b27d 2965
f013db32 2966 rphy->identify = identify;
0c33b27d
CH
2967 error = sas_rphy_add(rphy);
2968 if (error) {
d6ecdd63 2969 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2970 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2971 __func__, __LINE__));
0c33b27d 2972 sas_rphy_free(rphy);
547f9a21 2973 goto out;
0c33b27d 2974 }
d6ecdd63 2975 mptsas_set_rphy(ioc, phy_info, rphy);
0c33b27d
CH
2976 }
2977
547f9a21
EM
2978 out:
2979 return error;
0c33b27d
CH
2980}
2981
2982static int
e6b2d76a 2983mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 2984{
e6b2d76a 2985 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
2986 int error = -ENOMEM, i;
2987
f9c34022 2988 hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
e6b2d76a 2989 if (! hba)
0c33b27d 2990 goto out;
0c33b27d 2991
e6b2d76a 2992 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
2993 if (error)
2994 goto out_free_port_info;
2995
edb9068d 2996 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 2997 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 2998 port_info = ioc->hba_port_info;
e6b2d76a 2999 if (!port_info) {
f9c34022
KD
3000 ioc->hba_port_info = port_info = hba;
3001 ioc->hba_port_num_phy = port_info->num_phys;
e6b2d76a
ME
3002 list_add_tail(&port_info->list, &ioc->sas_topology);
3003 } else {
2ecce492 3004 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
3005 port_info->phy_info[i].negotiated_link_rate =
3006 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
3007 port_info->phy_info[i].handle =
3008 hba->phy_info[i].handle;
3009 port_info->phy_info[i].port_id =
3010 hba->phy_info[i].port_id;
3011 }
547f9a21 3012 kfree(hba->phy_info);
e6b2d76a
ME
3013 kfree(hba);
3014 hba = NULL;
3015 }
9a28f49a 3016 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
3017#if defined(CPQ_CIM)
3018 ioc->num_ports = port_info->num_phys;
3019#endif
0c33b27d
CH
3020 for (i = 0; i < port_info->num_phys; i++) {
3021 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
3022 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
3023 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
f9c34022
KD
3024 port_info->phy_info[i].identify.handle =
3025 port_info->phy_info[i].handle;
0c33b27d 3026 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
3027 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3028 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
f9c34022
KD
3029 port_info->phy_info[i].identify.handle);
3030 if (!ioc->hba_port_sas_addr)
3031 ioc->hba_port_sas_addr =
3032 port_info->phy_info[i].identify.sas_address;
024358ee 3033 port_info->phy_info[i].identify.phy_id =
2ecce492 3034 port_info->phy_info[i].phy_id = i;
547f9a21 3035 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
3036 mptsas_sas_device_pg0(ioc,
3037 &port_info->phy_info[i].attached,
3038 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3039 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3040 port_info->phy_info[i].attached.handle);
547f9a21 3041 }
0c33b27d 3042
547f9a21
EM
3043 mptsas_setup_wide_ports(ioc, port_info);
3044
3045 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 3046 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 3047 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
3048
3049 return 0;
3050
3051 out_free_port_info:
547f9a21 3052 kfree(hba);
0c33b27d
CH
3053 out:
3054 return error;
3055}
3056
f9c34022
KD
3057static void
3058mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
0c33b27d 3059{
f9c34022
KD
3060 struct mptsas_portinfo *parent;
3061 struct device *parent_dev;
3062 struct sas_rphy *rphy;
3063 int i;
3064 u64 sas_address; /* expander sas address */
3065 u32 handle;
9a28f49a 3066
f9c34022
KD
3067 handle = port_info->phy_info[0].handle;
3068 sas_address = port_info->phy_info[0].identify.sas_address;
0c33b27d 3069 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d 3070 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
f9c34022
KD
3071 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
3072 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
0c33b27d 3073
f9c34022
KD
3074 mptsas_sas_device_pg0(ioc,
3075 &port_info->phy_info[i].identify,
3076 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3077 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3078 port_info->phy_info[i].identify.handle);
3079 port_info->phy_info[i].identify.phy_id =
3080 port_info->phy_info[i].phy_id;
0c33b27d
CH
3081
3082 if (port_info->phy_info[i].attached.handle) {
3083 mptsas_sas_device_pg0(ioc,
f9c34022
KD
3084 &port_info->phy_info[i].attached,
3085 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3086 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3087 port_info->phy_info[i].attached.handle);
db9c9174
ME
3088 port_info->phy_info[i].attached.phy_id =
3089 port_info->phy_info[i].phy_id;
0c33b27d 3090 }
547f9a21 3091 }
0c33b27d 3092
f9c34022
KD
3093 mutex_lock(&ioc->sas_topology_mutex);
3094 parent = mptsas_find_portinfo_by_handle(ioc,
3095 port_info->phy_info[0].identify.handle_parent);
3096 if (!parent) {
9a28f49a 3097 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
3098 return;
3099 }
3100 for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
3101 i++) {
3102 if (parent->phy_info[i].attached.sas_address == sas_address) {
3103 rphy = mptsas_get_rphy(&parent->phy_info[i]);
3104 parent_dev = &rphy->dev;
3105 }
547f9a21 3106 }
f9c34022 3107 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
3108
3109 mptsas_setup_wide_ports(ioc, port_info);
547f9a21 3110 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
f9c34022 3111 mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
e6b2d76a 3112 ioc->sas_index, 0);
f9c34022 3113}
0c33b27d 3114
f9c34022
KD
3115static void
3116mptsas_expander_event_add(MPT_ADAPTER *ioc,
3117 MpiEventDataSasExpanderStatusChange_t *expander_data)
3118{
3119 struct mptsas_portinfo *port_info;
3120 int i;
3121 __le64 sas_address;
0c33b27d 3122
f9c34022
KD
3123 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3124 if (!port_info)
3125 BUG();
3126 port_info->num_phys = (expander_data->NumPhys) ?
3127 expander_data->NumPhys : 1;
3128 port_info->phy_info = kcalloc(port_info->num_phys,
3129 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
3130 if (!port_info->phy_info)
3131 BUG();
3132 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3133 for (i = 0; i < port_info->num_phys; i++) {
3134 port_info->phy_info[i].portinfo = port_info;
3135 port_info->phy_info[i].handle =
3136 le16_to_cpu(expander_data->DevHandle);
3137 port_info->phy_info[i].identify.sas_address =
3138 le64_to_cpu(sas_address);
3139 port_info->phy_info[i].identify.handle_parent =
3140 le16_to_cpu(expander_data->ParentDevHandle);
e6b2d76a 3141 }
f9c34022
KD
3142
3143 mutex_lock(&ioc->sas_topology_mutex);
3144 list_add_tail(&port_info->list, &ioc->sas_topology);
3145 mutex_unlock(&ioc->sas_topology_mutex);
3146
3147 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3148 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3149 (unsigned long long)sas_address);
3150
3151 mptsas_expander_refresh(ioc, port_info);
0c33b27d
CH
3152}
3153
f9c34022
KD
3154/**
3155 * mptsas_delete_expander_siblings - remove siblings attached to expander
3156 * @ioc: Pointer to MPT_ADAPTER structure
3157 * @parent: the parent port_info object
3158 * @expander: the expander port_info object
3159 **/
e6b2d76a 3160static void
f9c34022
KD
3161mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
3162 *parent, struct mptsas_portinfo *expander)
e6b2d76a 3163{
547f9a21 3164 struct mptsas_phyinfo *phy_info;
f9c34022
KD
3165 struct mptsas_portinfo *port_info;
3166 struct sas_rphy *rphy;
e6b2d76a
ME
3167 int i;
3168
f9c34022
KD
3169 phy_info = expander->phy_info;
3170 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3171 rphy = mptsas_get_rphy(phy_info);
3172 if (!rphy)
3173 continue;
3174 if (rphy->identify.device_type == SAS_END_DEVICE)
3175 mptsas_del_end_device(ioc, phy_info);
3176 }
e6b2d76a 3177
f9c34022
KD
3178 phy_info = expander->phy_info;
3179 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3180 rphy = mptsas_get_rphy(phy_info);
3181 if (!rphy)
e6b2d76a 3182 continue;
f9c34022
KD
3183 if (rphy->identify.device_type ==
3184 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
3185 rphy->identify.device_type ==
3186 MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
3187 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3188 rphy->identify.sas_address);
3189 if (!port_info)
3190 continue;
3191 if (port_info == parent) /* backlink rphy */
3192 continue;
3193 /*
3194 Delete this expander even if the expdevpage is exists
3195 because the parent expander is already deleted
3196 */
3197 mptsas_expander_delete(ioc, port_info, 1);
3198 }
3199 }
3200}
e6b2d76a 3201
e6b2d76a 3202
f9c34022
KD
3203/**
3204 * mptsas_expander_delete - remove this expander
3205 * @ioc: Pointer to MPT_ADAPTER structure
3206 * @port_info: expander port_info struct
3207 * @force: Flag to forcefully delete the expander
3208 *
3209 **/
e6b2d76a 3210
f9c34022
KD
3211static void mptsas_expander_delete(MPT_ADAPTER *ioc,
3212 struct mptsas_portinfo *port_info, u8 force)
3213{
e6b2d76a 3214
f9c34022
KD
3215 struct mptsas_portinfo *parent;
3216 int i;
3217 u64 expander_sas_address;
3218 struct mptsas_phyinfo *phy_info;
3219 struct mptsas_portinfo buffer;
3220 struct mptsas_portinfo_details *port_details;
3221 struct sas_port *port;
547f9a21 3222
f9c34022
KD
3223 if (!port_info)
3224 return;
547f9a21 3225
f9c34022
KD
3226 /* see if expander is still there before deleting */
3227 mptsas_sas_expander_pg0(ioc, &buffer,
3228 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3229 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
3230 port_info->phy_info[0].identify.handle);
547f9a21 3231
f9c34022 3232 if (buffer.num_phys) {
547f9a21 3233 kfree(buffer.phy_info);
f9c34022
KD
3234 if (!force)
3235 return;
e6b2d76a 3236 }
f9c34022
KD
3237
3238
3239 /*
3240 * Obtain the port_info instance to the parent port
3241 */
3242 port_details = NULL;
3243 expander_sas_address =
3244 port_info->phy_info[0].identify.sas_address;
3245 parent = mptsas_find_portinfo_by_handle(ioc,
3246 port_info->phy_info[0].identify.handle_parent);
3247 mptsas_delete_expander_siblings(ioc, parent, port_info);
3248 if (!parent)
3249 goto out;
3250
3251 /*
3252 * Delete rphys in the parent that point
3253 * to this expander.
3254 */
3255 phy_info = parent->phy_info;
3256 port = NULL;
3257 for (i = 0; i < parent->num_phys; i++, phy_info++) {
3258 if (!phy_info->phy)
3259 continue;
3260 if (phy_info->attached.sas_address !=
3261 expander_sas_address)
3262 continue;
3263 if (!port) {
3264 port = mptsas_get_port(phy_info);
3265 port_details = phy_info->port_details;
3266 }
3267 dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3268 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3269 phy_info->phy_id, phy_info->phy);
3270 sas_port_delete_phy(port, phy_info->phy);
3271 }
3272 if (port) {
3273 dev_printk(KERN_DEBUG, &port->dev,
3274 MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3275 ioc->name, port->port_identifier,
3276 (unsigned long long)expander_sas_address);
3277 sas_port_delete(port);
3278 mptsas_port_delete(ioc, port_details);
3279 }
3280 out:
3281
3282 printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3283 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3284 (unsigned long long)expander_sas_address);
3285
3286 /*
3287 * free link
3288 */
3289 list_del(&port_info->list);
3290 kfree(port_info->phy_info);
3291 kfree(port_info);
e6b2d76a
ME
3292}
3293
f9c34022
KD
3294
3295/**
3296 * mptsas_send_expander_event - expanders events
3297 * @ioc: Pointer to MPT_ADAPTER structure
3298 * @expander_data: event data
3299 *
3300 *
3301 * This function handles adding, removing, and refreshing
3302 * device handles within the expander objects.
e6b2d76a 3303 */
0c33b27d 3304static void
f9c34022 3305mptsas_send_expander_event(struct fw_event_work *fw_event)
0c33b27d 3306{
f9c34022
KD
3307 MPT_ADAPTER *ioc;
3308 MpiEventDataSasExpanderStatusChange_t *expander_data;
3309 struct mptsas_portinfo *port_info;
3310 __le64 sas_address;
f44e5461 3311 int i;
0c33b27d 3312
f9c34022
KD
3313 ioc = fw_event->ioc;
3314 expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3315 fw_event->event_data;
3316 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3317 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3318
3319 if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3320 if (port_info) {
3321 for (i = 0; i < port_info->num_phys; i++) {
3322 port_info->phy_info[i].portinfo = port_info;
3323 port_info->phy_info[i].handle =
3324 le16_to_cpu(expander_data->DevHandle);
3325 port_info->phy_info[i].identify.sas_address =
3326 le64_to_cpu(sas_address);
3327 port_info->phy_info[i].identify.handle_parent =
3328 le16_to_cpu(expander_data->ParentDevHandle);
3329 }
3330 mptsas_expander_refresh(ioc, port_info);
3331 } else if (!port_info && expander_data->NumPhys)
3332 mptsas_expander_event_add(ioc, expander_data);
3333 } else if (expander_data->ReasonCode ==
3334 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3335 mptsas_expander_delete(ioc, port_info, 0);
3336
3337 mptsas_free_fw_event(ioc, fw_event);
3338}
3339
3340
3341/**
3342 * mptsas_expander_add -
3343 * @ioc: Pointer to MPT_ADAPTER structure
3344 * @handle:
3345 *
3346 */
3347struct mptsas_portinfo *
3348mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3349{
3350 struct mptsas_portinfo buffer, *port_info;
3351 int i;
3352
3353 if ((mptsas_sas_expander_pg0(ioc, &buffer,
3354 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3355 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3356 return NULL;
3357
3358 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3359 if (!port_info) {
3360 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3361 "%s: exit at line=%d\n", ioc->name,
3362 __func__, __LINE__));
3363 return NULL;
3364 }
3365 port_info->num_phys = buffer.num_phys;
3366 port_info->phy_info = buffer.phy_info;
3367 for (i = 0; i < port_info->num_phys; i++)
3368 port_info->phy_info[i].portinfo = port_info;
3369 mutex_lock(&ioc->sas_topology_mutex);
3370 list_add_tail(&port_info->list, &ioc->sas_topology);
3371 mutex_unlock(&ioc->sas_topology_mutex);
3372 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3373 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3374 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3375 mptsas_expander_refresh(ioc, port_info);
3376 return port_info;
3377}
3378
3379static void
3380mptsas_send_link_status_event(struct fw_event_work *fw_event)
3381{
3382 MPT_ADAPTER *ioc;
3383 MpiEventDataSasPhyLinkStatus_t *link_data;
3384 struct mptsas_portinfo *port_info;
3385 struct mptsas_phyinfo *phy_info = NULL;
3386 __le64 sas_address;
3387 u8 phy_num;
3388 u8 link_rate;
3389
3390 ioc = fw_event->ioc;
3391 link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3392
3393 memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3394 sas_address = le64_to_cpu(sas_address);
3395 link_rate = link_data->LinkRates >> 4;
3396 phy_num = link_data->PhyNum;
3397
3398 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3399 if (port_info) {
3400 phy_info = &port_info->phy_info[phy_num];
3401 if (phy_info)
3402 phy_info->negotiated_link_rate = link_rate;
3403 }
3404
3405 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3406 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3407
eedf92b9
KD
3408 if (!port_info) {
3409 if (ioc->old_sas_discovery_protocal) {
3410 port_info = mptsas_expander_add(ioc,
3411 le16_to_cpu(link_data->DevHandle));
3412 if (port_info)
3413 goto out;
3414 }
f9c34022 3415 goto out;
eedf92b9 3416 }
f9c34022
KD
3417
3418 if (port_info == ioc->hba_port_info)
3419 mptsas_probe_hba_phys(ioc);
3420 else
3421 mptsas_expander_refresh(ioc, port_info);
3422 } else if (phy_info && phy_info->phy) {
3423 if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3424 phy_info->phy->negotiated_linkrate =
3425 SAS_PHY_DISABLED;
3426 else if (link_rate ==
3427 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3428 phy_info->phy->negotiated_linkrate =
3429 SAS_LINK_RATE_FAILED;
3430 else
3431 phy_info->phy->negotiated_linkrate =
3432 SAS_LINK_RATE_UNKNOWN;
f44e5461
ME
3433 }
3434 out:
f9c34022 3435 mptsas_free_fw_event(ioc, fw_event);
e6b2d76a
ME
3436}
3437
eedf92b9
KD
3438static void
3439mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3440{
3441 struct mptsas_portinfo buffer, *port_info;
3442 struct mptsas_device_info *sas_info;
3443 struct mptsas_devinfo sas_device;
3444 u32 handle;
3445 VirtTarget *vtarget = NULL;
3446 struct mptsas_phyinfo *phy_info;
3447 u8 found_expander;
3448 int retval, retry_count;
3449 unsigned long flags;
3450
3451 mpt_findImVolumes(ioc);
3452
3453 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3454 if (ioc->ioc_reset_in_progress) {
3455 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3456 "%s: exiting due to a parallel reset \n", ioc->name,
3457 __func__));
3458 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3459 return;
3460 }
3461 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3462
3463 /* devices, logical volumes */
3464 mutex_lock(&ioc->sas_device_info_mutex);
3465 redo_device_scan:
3466 list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
57e98513
KD
3467 if (sas_info->is_cached)
3468 continue;
a7938b0b
KD
3469 if (!sas_info->is_logical_volume) {
3470 sas_device.handle = 0;
3471 retry_count = 0;
eedf92b9 3472retry_page:
a7938b0b 3473 retval = mptsas_sas_device_pg0(ioc, &sas_device,
eedf92b9
KD
3474 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3475 << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3476 (sas_info->fw.channel << 8) +
3477 sas_info->fw.id);
3478
a7938b0b
KD
3479 if (sas_device.handle)
3480 continue;
3481 if (retval == -EBUSY) {
3482 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3483 if (ioc->ioc_reset_in_progress) {
3484 dfailprintk(ioc,
3485 printk(MYIOC_s_DEBUG_FMT
3486 "%s: exiting due to reset\n",
3487 ioc->name, __func__));
3488 spin_unlock_irqrestore
3489 (&ioc->taskmgmt_lock, flags);
3490 mutex_unlock(&ioc->
3491 sas_device_info_mutex);
3492 return;
3493 }
3494 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3495 flags);
eedf92b9 3496 }
eedf92b9 3497
a7938b0b
KD
3498 if (retval && (retval != -ENODEV)) {
3499 if (retry_count < 10) {
3500 retry_count++;
3501 goto retry_page;
3502 } else {
3503 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3504 "%s: Config page retry exceeded retry "
3505 "count deleting device 0x%llx\n",
3506 ioc->name, __func__,
3507 sas_info->sas_address));
3508 }
eedf92b9 3509 }
eedf92b9 3510
a7938b0b
KD
3511 /* delete device */
3512 vtarget = mptsas_find_vtarget(ioc,
eedf92b9 3513 sas_info->fw.channel, sas_info->fw.id);
a7938b0b
KD
3514
3515 if (vtarget)
3516 vtarget->deleted = 1;
3517
3518 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3519 sas_info->sas_address);
3520
3521 if (phy_info) {
3522 mptsas_del_end_device(ioc, phy_info);
3523 goto redo_device_scan;
3524 }
3525 } else
3526 mptsas_volume_delete(ioc, sas_info->fw.id);
eedf92b9 3527 }
129dd981 3528 mutex_unlock(&ioc->sas_device_info_mutex);
eedf92b9
KD
3529
3530 /* expanders */
3531 mutex_lock(&ioc->sas_topology_mutex);
3532 redo_expander_scan:
3533 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3534
3535 if (port_info->phy_info &&
3536 (!(port_info->phy_info[0].identify.device_info &
3537 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
3538 continue;
3539 found_expander = 0;
3540 handle = 0xFFFF;
3541 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3542 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3543 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3544 !found_expander) {
3545
3546 handle = buffer.phy_info[0].handle;
3547 if (buffer.phy_info[0].identify.sas_address ==
3548 port_info->phy_info[0].identify.sas_address) {
3549 found_expander = 1;
3550 }
3551 kfree(buffer.phy_info);
3552 }
3553
3554 if (!found_expander) {
3555 mptsas_expander_delete(ioc, port_info, 0);
3556 goto redo_expander_scan;
3557 }
3558 }
129dd981 3559 mutex_unlock(&ioc->sas_topology_mutex);
eedf92b9
KD
3560}
3561
f9c34022
KD
3562/**
3563 * mptsas_probe_expanders - adding expanders
3564 * @ioc: Pointer to MPT_ADAPTER structure
3565 *
3566 **/
e6b2d76a 3567static void
f9c34022 3568mptsas_probe_expanders(MPT_ADAPTER *ioc)
e6b2d76a 3569{
f9c34022
KD
3570 struct mptsas_portinfo buffer, *port_info;
3571 u32 handle;
3572 int i;
e6b2d76a 3573
f9c34022
KD
3574 handle = 0xFFFF;
3575 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3576 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3577 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3578
3579 handle = buffer.phy_info[0].handle;
3580 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3581 buffer.phy_info[0].identify.sas_address);
3582
3583 if (port_info) {
3584 /* refreshing handles */
3585 for (i = 0; i < buffer.num_phys; i++) {
3586 port_info->phy_info[i].handle = handle;
3587 port_info->phy_info[i].identify.handle_parent =
3588 buffer.phy_info[0].identify.handle_parent;
3589 }
3590 mptsas_expander_refresh(ioc, port_info);
3591 kfree(buffer.phy_info);
3592 continue;
3593 }
3594
3595 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3596 if (!port_info) {
3597 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3598 "%s: exit at line=%d\n", ioc->name,
3599 __func__, __LINE__));
3600 return;
3601 }
3602 port_info->num_phys = buffer.num_phys;
3603 port_info->phy_info = buffer.phy_info;
3604 for (i = 0; i < port_info->num_phys; i++)
3605 port_info->phy_info[i].portinfo = port_info;
3606 mutex_lock(&ioc->sas_topology_mutex);
3607 list_add_tail(&port_info->list, &ioc->sas_topology);
3608 mutex_unlock(&ioc->sas_topology_mutex);
3609 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3610 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3611 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3612 mptsas_expander_refresh(ioc, port_info);
3613 }
3614}
3615
3616static void
3617mptsas_probe_devices(MPT_ADAPTER *ioc)
3618{
3619 u16 handle;
3620 struct mptsas_devinfo sas_device;
3621 struct mptsas_phyinfo *phy_info;
3622
3623 handle = 0xFFFF;
3624 while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3625 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3626
3627 handle = sas_device.handle;
3628
3629 if ((sas_device.device_info &
3630 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3631 MPI_SAS_DEVICE_INFO_STP_TARGET |
3632 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3633 continue;
3634
3635 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3636 if (!phy_info)
3637 continue;
3638
3639 if (mptsas_get_rphy(phy_info))
3640 continue;
3641
3642 mptsas_add_end_device(ioc, phy_info);
3643 }
547f9a21
EM
3644}
3645
2f187862
KD
3646/**
3647 * mptsas_scan_sas_topology -
3648 * @ioc: Pointer to MPT_ADAPTER structure
3649 * @sas_address:
3650 *
3651 **/
547f9a21 3652static void
f9c34022 3653mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
547f9a21 3654{
f9c34022
KD
3655 struct scsi_device *sdev;
3656 int i;
547f9a21 3657
f9c34022
KD
3658 mptsas_probe_hba_phys(ioc);
3659 mptsas_probe_expanders(ioc);
3660 mptsas_probe_devices(ioc);
0c33b27d 3661
f9c34022
KD
3662 /*
3663 Reporting RAID volumes.
3664 */
3665 if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
3666 !ioc->raid_data.pIocPg2->NumActiveVolumes)
3667 return;
3668 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3669 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3670 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3671 if (sdev) {
3672 scsi_device_put(sdev);
3673 continue;
3674 }
3675 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3676 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3677 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
3678 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3679 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3680 }
3681}
3eb0822c 3682
57e98513
KD
3683
3684static void
3685mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
3686{
3687 MPT_ADAPTER *ioc;
3688 EventDataQueueFull_t *qfull_data;
3689 struct mptsas_device_info *sas_info;
3690 struct scsi_device *sdev;
3691 int depth;
3692 int id = -1;
3693 int channel = -1;
3694 int fw_id, fw_channel;
3695 u16 current_depth;
3696
3697
3698 ioc = fw_event->ioc;
3699 qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
3700 fw_id = qfull_data->TargetID;
3701 fw_channel = qfull_data->Bus;
3702 current_depth = le16_to_cpu(qfull_data->CurrentDepth);
3703
3704 /* if hidden raid component, look for the volume id */
3705 mutex_lock(&ioc->sas_device_info_mutex);
3706 if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
3707 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
3708 list) {
3709 if (sas_info->is_cached ||
3710 sas_info->is_logical_volume)
3711 continue;
3712 if (sas_info->is_hidden_raid_component &&
3713 (sas_info->fw.channel == fw_channel &&
3714 sas_info->fw.id == fw_id)) {
3715 id = sas_info->volume_id;
3716 channel = MPTSAS_RAID_CHANNEL;
3717 goto out;
3718 }
3719 }
3720 } else {
3721 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
3722 list) {
3723 if (sas_info->is_cached ||
3724 sas_info->is_hidden_raid_component ||
3725 sas_info->is_logical_volume)
3726 continue;
3727 if (sas_info->fw.channel == fw_channel &&
3728 sas_info->fw.id == fw_id) {
3729 id = sas_info->os.id;
3730 channel = sas_info->os.channel;
3731 goto out;
3732 }
3733 }
3734
3735 }
3736
3737 out:
3738 mutex_unlock(&ioc->sas_device_info_mutex);
3739
3740 if (id != -1) {
3741 shost_for_each_device(sdev, ioc->sh) {
3742 if (sdev->id == id && sdev->channel == channel) {
3743 if (current_depth > sdev->queue_depth) {
3744 sdev_printk(KERN_INFO, sdev,
3745 "strange observation, the queue "
3746 "depth is (%d) meanwhile fw queue "
3747 "depth (%d)\n", sdev->queue_depth,
3748 current_depth);
3749 continue;
3750 }
3751 depth = scsi_track_queue_full(sdev,
3752 current_depth - 1);
3753 if (depth > 0)
3754 sdev_printk(KERN_INFO, sdev,
3755 "Queue depth reduced to (%d)\n",
3756 depth);
3757 else if (depth < 0)
3758 sdev_printk(KERN_INFO, sdev,
3759 "Tagged Command Queueing is being "
3760 "disabled\n");
3761 else if (depth == 0)
3762 sdev_printk(KERN_INFO, sdev,
3763 "Queue depth not changed yet\n");
3764 }
3765 }
3766 }
3767
3768 mptsas_free_fw_event(ioc, fw_event);
3769}
3770
3771
9a28f49a 3772static struct mptsas_phyinfo *
547f9a21 3773mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
3774{
3775 struct mptsas_portinfo *port_info;
9a28f49a 3776 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 3777 int i;
9a28f49a 3778
9a28f49a
CH
3779 mutex_lock(&ioc->sas_topology_mutex);
3780 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3781 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
3782 if (!mptsas_is_end_device(
3783 &port_info->phy_info[i].attached))
3784 continue;
547f9a21
EM
3785 if (port_info->phy_info[i].attached.sas_address
3786 != sas_address)
3787 continue;
b506ade9
EM
3788 phy_info = &port_info->phy_info[i];
3789 break;
3790 }
3791 }
3792 mutex_unlock(&ioc->sas_topology_mutex);
3793 return phy_info;
3794}
3795
a7938b0b
KD
3796/**
3797 * mptsas_find_phyinfo_by_phys_disk_num -
3798 * @ioc: Pointer to MPT_ADAPTER structure
3799 * @phys_disk_num:
3800 * @channel:
3801 * @id:
3802 *
3803 **/
9a28f49a 3804static struct mptsas_phyinfo *
a7938b0b
KD
3805mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
3806 u8 channel, u8 id)
9a28f49a 3807{
9a28f49a 3808 struct mptsas_phyinfo *phy_info = NULL;
a7938b0b
KD
3809 struct mptsas_portinfo *port_info;
3810 RaidPhysDiskPage1_t *phys_disk = NULL;
3811 int num_paths;
3812 u64 sas_address = 0;
9a28f49a
CH
3813 int i;
3814
a7938b0b
KD
3815 phy_info = NULL;
3816 if (!ioc->raid_data.pIocPg3)
3817 return NULL;
3818 /* dual port support */
3819 num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
3820 if (!num_paths)
3821 goto out;
3822 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
3823 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
3824 if (!phys_disk)
3825 goto out;
3826 mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
3827 for (i = 0; i < num_paths; i++) {
3828 if ((phys_disk->Path[i].Flags & 1) != 0)
3829 /* entry no longer valid */
3830 continue;
3831 if ((id == phys_disk->Path[i].PhysDiskID) &&
3832 (channel == phys_disk->Path[i].PhysDiskBus)) {
3833 memcpy(&sas_address, &phys_disk->Path[i].WWID,
3834 sizeof(u64));
3835 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3836 sas_address);
3837 goto out;
3838 }
3839 }
3840
3841 out:
3842 kfree(phys_disk);
3843 if (phy_info)
3844 return phy_info;
3845
3846 /*
3847 * Extra code to handle RAID0 case, where the sas_address is not updated
3848 * in phys_disk_page_1 when hotswapped
3849 */
9a28f49a
CH
3850 mutex_lock(&ioc->sas_topology_mutex);
3851 list_for_each_entry(port_info, &ioc->sas_topology, list) {
a7938b0b 3852 for (i = 0; i < port_info->num_phys && !phy_info; i++) {
547f9a21
EM
3853 if (!mptsas_is_end_device(
3854 &port_info->phy_info[i].attached))
3855 continue;
b506ade9
EM
3856 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
3857 continue;
a7938b0b
KD
3858 if ((port_info->phy_info[i].attached.phys_disk_num ==
3859 phys_disk_num) &&
3860 (port_info->phy_info[i].attached.id == id) &&
3861 (port_info->phy_info[i].attached.channel ==
3862 channel))
3863 phy_info = &port_info->phy_info[i];
547f9a21 3864 }
9a28f49a
CH
3865 }
3866 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
3867 return phy_info;
3868}
3869
f44e5461
ME
3870static void
3871mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
3872{
f99be43b
EM
3873 int rc;
3874
f44e5461 3875 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 3876 rc = scsi_device_reprobe(sdev);
f44e5461
ME
3877}
3878
3879static void
3880mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
3881{
3882 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
3883 mptsas_reprobe_lun);
3884}
3885
b506ade9
EM
3886static void
3887mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
3888{
3889 CONFIGPARMS cfg;
3890 ConfigPageHeader_t hdr;
3891 dma_addr_t dma_handle;
3892 pRaidVolumePage0_t buffer = NULL;
3893 RaidPhysDiskPage0_t phys_disk;
3894 int i;
3eb0822c
KD
3895 struct mptsas_phyinfo *phy_info;
3896 struct mptsas_devinfo sas_device;
b506ade9
EM
3897
3898 memset(&cfg, 0 , sizeof(CONFIGPARMS));
3899 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
3900 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
3901 cfg.pageAddr = (channel << 8) + id;
3902 cfg.cfghdr.hdr = &hdr;
3903 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3904
3905 if (mpt_config(ioc, &cfg) != 0)
3906 goto out;
3907
3908 if (!hdr.PageLength)
3909 goto out;
3910
3911 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
3912 &dma_handle);
3913
3914 if (!buffer)
3915 goto out;
3916
3917 cfg.physAddr = dma_handle;
3918 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3919
3920 if (mpt_config(ioc, &cfg) != 0)
3921 goto out;
3922
3923 if (!(buffer->VolumeStatus.Flags &
3924 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
3925 goto out;
3926
3927 if (!buffer->NumPhysDisks)
3928 goto out;
3929
3930 for (i = 0; i < buffer->NumPhysDisks; i++) {
3931
3932 if (mpt_raid_phys_disk_pg0(ioc,
3933 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
3934 continue;
3935
3eb0822c
KD
3936 if (mptsas_sas_device_pg0(ioc, &sas_device,
3937 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3938 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3939 (phys_disk.PhysDiskBus << 8) +
3940 phys_disk.PhysDiskID))
3941 continue;
b506ade9 3942
3eb0822c
KD
3943 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3944 sas_device.sas_address);
3945 mptsas_add_end_device(ioc, phy_info);
b506ade9
EM
3946 }
3947
3948 out:
3949 if (buffer)
3950 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
3951 dma_handle);
3952}
e6b2d76a
ME
3953/*
3954 * Work queue thread to handle SAS hotplug events
3955 */
9a28f49a 3956static void
3eb0822c
KD
3957mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
3958 struct mptsas_hotplug_event *hot_plug_info)
9a28f49a 3959{
9a28f49a 3960 struct mptsas_phyinfo *phy_info;
547f9a21 3961 struct scsi_target * starget;
c73787ee 3962 struct mptsas_devinfo sas_device;
f44e5461 3963 VirtTarget *vtarget;
3eb0822c 3964 int i;
9a28f49a 3965
3eb0822c 3966 switch (hot_plug_info->event_type) {
9a28f49a 3967
3eb0822c
KD
3968 case MPTSAS_ADD_PHYSDISK:
3969
3970 if (!ioc->raid_data.pIocPg2)
3971 break;
3972
3973 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3974 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
3975 hot_plug_info->id) {
3976 printk(MYIOC_s_WARN_FMT "firmware bug: unable "
3977 "to add hidden disk - target_id matchs "
3978 "volume_id\n", ioc->name);
3979 mptsas_free_fw_event(ioc, fw_event);
3980 return;
3981 }
b506ade9 3982 }
3eb0822c 3983 mpt_findImVolumes(ioc);
b506ade9 3984
3eb0822c
KD
3985 case MPTSAS_ADD_DEVICE:
3986 memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
3987 mptsas_sas_device_pg0(ioc, &sas_device,
3988 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3989 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3990 (hot_plug_info->channel << 8) +
3991 hot_plug_info->id);
3992
3993 if (!sas_device.handle)
3994 return;
3995
3996 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
b506ade9 3997 if (!phy_info)
3eb0822c 3998 break;
e6b2d76a 3999
3eb0822c
KD
4000 if (mptsas_get_rphy(phy_info))
4001 break;
4002
4003 mptsas_add_end_device(ioc, phy_info);
4004 break;
4005
4006 case MPTSAS_DEL_DEVICE:
4007 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4008 hot_plug_info->sas_address);
4009 mptsas_del_end_device(ioc, phy_info);
4010 break;
4011
4012 case MPTSAS_DEL_PHYSDISK:
4013
4014 mpt_findImVolumes(ioc);
4015
4016 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
a7938b0b
KD
4017 ioc, hot_plug_info->phys_disk_num,
4018 hot_plug_info->channel,
4019 hot_plug_info->id);
3eb0822c
KD
4020 mptsas_del_end_device(ioc, phy_info);
4021 break;
4022
4023 case MPTSAS_ADD_PHYSDISK_REPROBE:
4024
4025 if (mptsas_sas_device_pg0(ioc, &sas_device,
4026 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4027 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4028 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 4029 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4030 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4031 __func__, hot_plug_info->id, __LINE__));
b506ade9
EM
4032 break;
4033 }
3eb0822c
KD
4034
4035 phy_info = mptsas_find_phyinfo_by_sas_address(
4036 ioc, sas_device.sas_address);
4037
4038 if (!phy_info) {
d6ecdd63 4039 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4040 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4041 __func__, hot_plug_info->id, __LINE__));
9a28f49a 4042 break;
547f9a21 4043 }
3eb0822c
KD
4044
4045 starget = mptsas_get_starget(phy_info);
4046 if (!starget) {
d6ecdd63 4047 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4048 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4049 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
4050 break;
4051 }
b506ade9 4052
3eb0822c
KD
4053 vtarget = starget->hostdata;
4054 if (!vtarget) {
d6ecdd63 4055 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4056 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4057 __func__, hot_plug_info->id, __LINE__));
f44e5461 4058 break;
547f9a21
EM
4059 }
4060
3eb0822c 4061 mpt_findImVolumes(ioc);
547f9a21 4062
3eb0822c
KD
4063 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
4064 "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4065 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4066 hot_plug_info->phys_disk_num, (unsigned long long)
4067 sas_device.sas_address);
9a28f49a 4068
3eb0822c
KD
4069 vtarget->id = hot_plug_info->phys_disk_num;
4070 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4071 phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
4072 mptsas_reprobe_target(starget, 1);
9a28f49a 4073 break;
c73787ee 4074
3eb0822c 4075 case MPTSAS_DEL_PHYSDISK_REPROBE:
bd23e94c 4076
e3094447
CH
4077 if (mptsas_sas_device_pg0(ioc, &sas_device,
4078 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9 4079 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3eb0822c 4080 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 4081 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4082 "%s: fw_id=%d exit at line=%d\n",
4083 ioc->name, __func__,
4084 hot_plug_info->id, __LINE__));
e3094447 4085 break;
547f9a21 4086 }
9a28f49a 4087
547f9a21
EM
4088 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4089 sas_device.sas_address);
3eb0822c 4090 if (!phy_info) {
d6ecdd63 4091 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4092 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4093 __func__, hot_plug_info->id, __LINE__));
547f9a21 4094 break;
e6b2d76a
ME
4095 }
4096
547f9a21 4097 starget = mptsas_get_starget(phy_info);
3eb0822c
KD
4098 if (!starget) {
4099 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4100 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4101 __func__, hot_plug_info->id, __LINE__));
9a28f49a
CH
4102 break;
4103 }
4104
3eb0822c
KD
4105 vtarget = starget->hostdata;
4106 if (!vtarget) {
d6ecdd63 4107 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4108 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4109 __func__, hot_plug_info->id, __LINE__));
f44e5461 4110 break;
547f9a21 4111 }
b506ade9 4112
3eb0822c 4113 if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
d6ecdd63 4114 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4115 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4116 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
4117 break;
4118 }
c73787ee 4119
3eb0822c 4120 mpt_findImVolumes(ioc);
9a28f49a 4121
3eb0822c
KD
4122 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
4123 " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4124 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4125 hot_plug_info->phys_disk_num, (unsigned long long)
4126 sas_device.sas_address);
4127
4128 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4129 vtarget->id = hot_plug_info->id;
4130 phy_info->attached.phys_disk_num = ~0;
4131 mptsas_reprobe_target(starget, 0);
4132 mptsas_add_device_component_by_fw(ioc,
4133 hot_plug_info->channel, hot_plug_info->id);
9a28f49a 4134 break;
3eb0822c 4135
c73787ee 4136 case MPTSAS_ADD_RAID:
3eb0822c 4137
c73787ee 4138 mpt_findImVolumes(ioc);
3eb0822c
KD
4139 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4140 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4141 hot_plug_info->id);
4142 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4143 hot_plug_info->id, 0);
c73787ee 4144 break;
3eb0822c 4145
c73787ee 4146 case MPTSAS_DEL_RAID:
3eb0822c 4147
c73787ee 4148 mpt_findImVolumes(ioc);
3eb0822c
KD
4149 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4150 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4151 hot_plug_info->id);
4152 scsi_remove_device(hot_plug_info->sdev);
4153 scsi_device_put(hot_plug_info->sdev);
c73787ee 4154 break;
3eb0822c 4155
b506ade9 4156 case MPTSAS_ADD_INACTIVE_VOLUME:
3eb0822c
KD
4157
4158 mpt_findImVolumes(ioc);
b506ade9 4159 mptsas_adding_inactive_raid_components(ioc,
3eb0822c 4160 hot_plug_info->channel, hot_plug_info->id);
b506ade9 4161 break;
3eb0822c 4162
bd23e94c
ME
4163 default:
4164 break;
9a28f49a
CH
4165 }
4166
3eb0822c 4167 mptsas_free_fw_event(ioc, fw_event);
9a28f49a
CH
4168}
4169
4170static void
3eb0822c 4171mptsas_send_sas_event(struct fw_event_work *fw_event)
9a28f49a 4172{
3eb0822c
KD
4173 MPT_ADAPTER *ioc;
4174 struct mptsas_hotplug_event hot_plug_info;
4175 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
4176 u32 device_info;
4177 u64 sas_address;
4178
4179 ioc = fw_event->ioc;
4180 sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
4181 fw_event->event_data;
4182 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
9a28f49a
CH
4183
4184 if ((device_info &
3eb0822c
KD
4185 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
4186 MPI_SAS_DEVICE_INFO_STP_TARGET |
4187 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
4188 mptsas_free_fw_event(ioc, fw_event);
9a28f49a 4189 return;
3eb0822c
KD
4190 }
4191
4192 if (sas_event_data->ReasonCode ==
4193 MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
4194 mptbase_sas_persist_operation(ioc,
4195 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4196 mptsas_free_fw_event(ioc, fw_event);
4197 return;
4198 }
9a28f49a 4199
4b766471 4200 switch (sas_event_data->ReasonCode) {
4b766471 4201 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a 4202 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
3eb0822c
KD
4203 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4204 hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
4205 hot_plug_info.channel = sas_event_data->Bus;
4206 hot_plug_info.id = sas_event_data->TargetID;
4207 hot_plug_info.phy_id = sas_event_data->PhyNum;
4b766471 4208 memcpy(&sas_address, &sas_event_data->SASAddress,
3eb0822c
KD
4209 sizeof(u64));
4210 hot_plug_info.sas_address = le64_to_cpu(sas_address);
4211 hot_plug_info.device_info = device_info;
4b766471
ME
4212 if (sas_event_data->ReasonCode &
4213 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
3eb0822c 4214 hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4b766471 4215 else
3eb0822c
KD
4216 hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
4217 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4b766471 4218 break;
3eb0822c 4219
4b766471 4220 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
3eb0822c
KD
4221 mptbase_sas_persist_operation(ioc,
4222 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4223 mptsas_free_fw_event(ioc, fw_event);
4b766471 4224 break;
3eb0822c 4225
4b766471 4226 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
3eb0822c 4227 /* TODO */
4b766471 4228 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
3eb0822c 4229 /* TODO */
4b766471 4230 default:
3eb0822c 4231 mptsas_free_fw_event(ioc, fw_event);
4b766471 4232 break;
9a28f49a 4233 }
9a28f49a 4234}
3eb0822c 4235
c73787ee 4236static void
3eb0822c 4237mptsas_send_raid_event(struct fw_event_work *fw_event)
c73787ee 4238{
3eb0822c
KD
4239 MPT_ADAPTER *ioc;
4240 EVENT_DATA_RAID *raid_event_data;
4241 struct mptsas_hotplug_event hot_plug_info;
4242 int status;
4243 int state;
4244 struct scsi_device *sdev = NULL;
4245 VirtDevice *vdevice = NULL;
4246 RaidPhysDiskPage0_t phys_disk;
4247
4248 ioc = fw_event->ioc;
4249 raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
4250 status = le32_to_cpu(raid_event_data->SettingsStatus);
4251 state = (status >> 8) & 0xff;
4252
4253 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4254 hot_plug_info.id = raid_event_data->VolumeID;
4255 hot_plug_info.channel = raid_event_data->VolumeBus;
4256 hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
4257
4258 if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
4259 raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
4260 raid_event_data->ReasonCode ==
4261 MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
4262 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4263 hot_plug_info.id, 0);
4264 hot_plug_info.sdev = sdev;
4265 if (sdev)
4266 vdevice = sdev->hostdata;
c73787ee
ME
4267 }
4268
3eb0822c
KD
4269 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4270 "ReasonCode=%02x\n", ioc->name, __func__,
4271 raid_event_data->ReasonCode));
c73787ee
ME
4272
4273 switch (raid_event_data->ReasonCode) {
4274 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
3eb0822c 4275 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
c73787ee
ME
4276 break;
4277 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
3eb0822c 4278 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
c73787ee 4279 break;
bd23e94c
ME
4280 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4281 switch (state) {
4282 case MPI_PD_STATE_ONLINE:
b506ade9 4283 case MPI_PD_STATE_NOT_COMPATIBLE:
3eb0822c
KD
4284 mpt_raid_phys_disk_pg0(ioc,
4285 raid_event_data->PhysDiskNum, &phys_disk);
4286 hot_plug_info.id = phys_disk.PhysDiskID;
4287 hot_plug_info.channel = phys_disk.PhysDiskBus;
4288 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
bd23e94c 4289 break;
3eb0822c 4290 case MPI_PD_STATE_FAILED:
bd23e94c 4291 case MPI_PD_STATE_MISSING:
bd23e94c
ME
4292 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
4293 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
4294 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
3eb0822c 4295 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
bd23e94c
ME
4296 break;
4297 default:
4298 break;
4299 }
4300 break;
c73787ee 4301 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
3eb0822c
KD
4302 if (!sdev)
4303 break;
4304 vdevice->vtarget->deleted = 1; /* block IO */
4305 hot_plug_info.event_type = MPTSAS_DEL_RAID;
c73787ee
ME
4306 break;
4307 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
3eb0822c
KD
4308 if (sdev) {
4309 scsi_device_put(sdev);
4310 break;
4311 }
4312 hot_plug_info.event_type = MPTSAS_ADD_RAID;
c73787ee
ME
4313 break;
4314 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
3eb0822c
KD
4315 if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
4316 if (!sdev)
4317 break;
4318 vdevice->vtarget->deleted = 1; /* block IO */
4319 hot_plug_info.event_type = MPTSAS_DEL_RAID;
4320 break;
4321 }
bd23e94c
ME
4322 switch (state) {
4323 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
4324 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
3eb0822c
KD
4325 if (!sdev)
4326 break;
4327 vdevice->vtarget->deleted = 1; /* block IO */
4328 hot_plug_info.event_type = MPTSAS_DEL_RAID;
bd23e94c
ME
4329 break;
4330 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
4331 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3eb0822c
KD
4332 if (sdev) {
4333 scsi_device_put(sdev);
4334 break;
4335 }
4336 hot_plug_info.event_type = MPTSAS_ADD_RAID;
bd23e94c
ME
4337 break;
4338 default:
4339 break;
4340 }
c73787ee
ME
4341 break;
4342 default:
4343 break;
4344 }
3eb0822c
KD
4345
4346 if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
4347 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4348 else
4349 mptsas_free_fw_event(ioc, fw_event);
c73787ee
ME
4350}
4351
db7051b2
KD
4352/**
4353 * mptsas_issue_tm - send mptsas internal tm request
4354 * @ioc: Pointer to MPT_ADAPTER structure
4355 * @type: Task Management type
4356 * @channel: channel number for task management
4357 * @id: Logical Target ID for reset (if appropriate)
4358 * @lun: Logical unit for reset (if appropriate)
4359 * @task_context: Context for the task to be aborted
4360 * @timeout: timeout for task management control
4361 *
4362 * return 0 on success and -1 on failure:
4363 *
4364 */
4365static int
4366mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4367 int task_context, ulong timeout, u8 *issue_reset)
4368{
4369 MPT_FRAME_HDR *mf;
4370 SCSITaskMgmt_t *pScsiTm;
4371 int retval;
4372 unsigned long timeleft;
4373
4374 *issue_reset = 0;
4375 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4376 if (mf == NULL) {
4377 retval = -1; /* return failure */
4378 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4379 "msg frames!!\n", ioc->name));
4380 goto out;
4381 }
4382
4383 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4384 "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4385 "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4386 type, timeout, channel, id, (unsigned long long)lun,
4387 task_context));
4388
4389 pScsiTm = (SCSITaskMgmt_t *) mf;
4390 memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4391 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4392 pScsiTm->TaskType = type;
4393 pScsiTm->MsgFlags = 0;
4394 pScsiTm->TargetID = id;
4395 pScsiTm->Bus = channel;
4396 pScsiTm->ChainOffset = 0;
4397 pScsiTm->Reserved = 0;
4398 pScsiTm->Reserved1 = 0;
4399 pScsiTm->TaskMsgContext = task_context;
4400 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4401
4402 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4403 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4404 retval = 0;
4405 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4406
4407 /* Now wait for the command to complete */
4408 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4409 timeout*HZ);
4410 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4411 retval = -1; /* return failure */
4412 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4413 "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4414 mpt_free_msg_frame(ioc, mf);
4415 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4416 goto out;
4417 *issue_reset = 1;
4418 goto out;
4419 }
4420
4421 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4422 retval = -1; /* return failure */
4423 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4424 "TaskMgmt request: failed with no reply\n", ioc->name));
4425 goto out;
4426 }
4427
4428 out:
4429 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4430 return retval;
4431}
4432
4433/**
4434 * mptsas_broadcast_primative_work - Handle broadcast primitives
4435 * @work: work queue payload containing info describing the event
4436 *
4437 * this will be handled in workqueue context.
4438 */
4439static void
4440mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
4441{
4442 MPT_ADAPTER *ioc = fw_event->ioc;
4443 MPT_FRAME_HDR *mf;
4444 VirtDevice *vdevice;
4445 int ii;
4446 struct scsi_cmnd *sc;
4447 SCSITaskMgmtReply_t *pScsiTmReply;
4448 u8 issue_reset;
4449 int task_context;
4450 u8 channel, id;
4451 int lun;
4452 u32 termination_count;
4453 u32 query_count;
4454
4455 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4456 "%s - enter\n", ioc->name, __func__));
4457
4458 mutex_lock(&ioc->taskmgmt_cmds.mutex);
4459 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4460 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4461 mptsas_requeue_fw_event(ioc, fw_event, 1000);
4462 return;
4463 }
4464
4465 issue_reset = 0;
4466 termination_count = 0;
4467 query_count = 0;
4468 mpt_findImVolumes(ioc);
4469 pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4470
4471 for (ii = 0; ii < ioc->req_depth; ii++) {
4472 if (ioc->fw_events_off)
4473 goto out;
4474 sc = mptscsih_get_scsi_lookup(ioc, ii);
4475 if (!sc)
4476 continue;
4477 mf = MPT_INDEX_2_MFPTR(ioc, ii);
4478 if (!mf)
4479 continue;
4480 task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4481 vdevice = sc->device->hostdata;
4482 if (!vdevice || !vdevice->vtarget)
4483 continue;
4484 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4485 continue; /* skip hidden raid components */
4486 if (vdevice->vtarget->raidVolume)
4487 continue; /* skip hidden raid components */
4488 channel = vdevice->vtarget->channel;
4489 id = vdevice->vtarget->id;
4490 lun = vdevice->lun;
4491 if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4492 channel, id, (u64)lun, task_context, 30, &issue_reset))
4493 goto out;
4494 query_count++;
4495 termination_count +=
4496 le32_to_cpu(pScsiTmReply->TerminationCount);
4497 if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4498 (pScsiTmReply->ResponseCode ==
4499 MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4500 pScsiTmReply->ResponseCode ==
4501 MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4502 continue;
4503 if (mptsas_issue_tm(ioc,
4504 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4505 channel, id, (u64)lun, 0, 30, &issue_reset))
4506 goto out;
4507 termination_count +=
4508 le32_to_cpu(pScsiTmReply->TerminationCount);
4509 }
4510
4511 out:
4512 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4513 "%s - exit, query_count = %d termination_count = %d\n",
4514 ioc->name, __func__, query_count, termination_count));
4515
4516 ioc->broadcast_aen_busy = 0;
4517 mpt_clear_taskmgmt_in_progress_flag(ioc);
4518 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4519
4520 if (issue_reset) {
4521 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
4522 ioc->name, __func__);
4523 mpt_HardResetHandler(ioc, CAN_SLEEP);
4524 }
4525 mptsas_free_fw_event(ioc, fw_event);
4526}
4527
b506ade9
EM
4528/*
4529 * mptsas_send_ir2_event - handle exposing hidden disk when
4530 * an inactive raid volume is added
4531 *
4532 * @ioc: Pointer to MPT_ADAPTER structure
4533 * @ir2_data
4534 *
4535 */
4536static void
3eb0822c 4537mptsas_send_ir2_event(struct fw_event_work *fw_event)
b506ade9 4538{
3eb0822c
KD
4539 MPT_ADAPTER *ioc;
4540 struct mptsas_hotplug_event hot_plug_info;
4541 MPI_EVENT_DATA_IR2 *ir2_data;
4542 u8 reasonCode;
a7938b0b 4543 RaidPhysDiskPage0_t phys_disk;
3eb0822c
KD
4544
4545 ioc = fw_event->ioc;
4546 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
4547 reasonCode = ir2_data->ReasonCode;
4548
4549 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4550 "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
4551
4552 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4553 hot_plug_info.id = ir2_data->TargetID;
4554 hot_plug_info.channel = ir2_data->Bus;
4555 switch (reasonCode) {
4556 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
4557 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
4558 break;
a7938b0b
KD
4559 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
4560 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4561 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4562 break;
4563 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
4564 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4565 mpt_raid_phys_disk_pg0(ioc,
4566 ir2_data->PhysDiskNum, &phys_disk);
4567 hot_plug_info.id = phys_disk.PhysDiskID;
4568 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4569 break;
3eb0822c
KD
4570 default:
4571 mptsas_free_fw_event(ioc, fw_event);
b506ade9 4572 return;
3eb0822c
KD
4573 }
4574 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4575}
e6b2d76a 4576
9a28f49a
CH
4577static int
4578mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4579{
3eb0822c
KD
4580 u32 event = le32_to_cpu(reply->Event);
4581 int sz, event_data_sz;
4582 struct fw_event_work *fw_event;
4583 unsigned long delay;
9a28f49a 4584
3eb0822c
KD
4585 /* events turned off due to host reset or driver unloading */
4586 if (ioc->fw_events_off)
4587 return 0;
e6b2d76a 4588
3eb0822c 4589 delay = msecs_to_jiffies(1);
9a28f49a 4590 switch (event) {
db7051b2
KD
4591 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
4592 {
4593 EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
4594 (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
4595 if (broadcast_event_data->Primitive !=
4596 MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
4597 return 0;
4598 if (ioc->broadcast_aen_busy)
4599 return 0;
4600 ioc->broadcast_aen_busy = 1;
4601 break;
4602 }
9a28f49a 4603 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
3eb0822c
KD
4604 {
4605 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
4606 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
4607
4608 if (sas_event_data->ReasonCode ==
4609 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
4610 mptsas_target_reset_queue(ioc, sas_event_data);
4611 return 0;
4612 }
79de278e 4613 break;
3eb0822c 4614 }
f9c34022
KD
4615 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
4616 {
4617 MpiEventDataSasExpanderStatusChange_t *expander_data =
4618 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
4619
eedf92b9
KD
4620 if (ioc->old_sas_discovery_protocal)
4621 return 0;
f9c34022
KD
4622
4623 if (expander_data->ReasonCode ==
4624 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
4625 ioc->device_missing_delay)
4626 delay = HZ * ioc->device_missing_delay;
e6b2d76a 4627 break;
f9c34022
KD
4628 }
4629 case MPI_EVENT_SAS_DISCOVERY:
4630 {
4631 u32 discovery_status;
4632 EventDataSasDiscovery_t *discovery_data =
4633 (EventDataSasDiscovery_t *)reply->Data;
4634
4635 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
4636 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
eedf92b9
KD
4637 if (ioc->old_sas_discovery_protocal && !discovery_status)
4638 mptsas_queue_rescan(ioc);
f9c34022
KD
4639 return 0;
4640 }
3eb0822c
KD
4641 case MPI_EVENT_INTEGRATED_RAID:
4642 case MPI_EVENT_PERSISTENT_TABLE_FULL:
b506ade9 4643 case MPI_EVENT_IR2:
3eb0822c
KD
4644 case MPI_EVENT_SAS_PHY_LINK_STATUS:
4645 case MPI_EVENT_QUEUE_FULL:
b506ade9 4646 break;
9a28f49a 4647 default:
3eb0822c 4648 return 0;
9a28f49a 4649 }
c73787ee 4650
3eb0822c
KD
4651 event_data_sz = ((reply->MsgLength * 4) -
4652 offsetof(EventNotificationReply_t, Data));
4653 sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
4654 fw_event = kzalloc(sz, GFP_ATOMIC);
4655 if (!fw_event) {
4656 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
4657 __func__, __LINE__);
4658 return 0;
4659 }
4660 memcpy(fw_event->event_data, reply->Data, event_data_sz);
4661 fw_event->event = event;
4662 fw_event->ioc = ioc;
4663 mptsas_add_fw_event(ioc, fw_event, delay);
4664 return 0;
9a28f49a
CH
4665}
4666
a7938b0b
KD
4667/* Delete a volume when no longer listed in ioc pg2
4668 */
4669static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
4670{
4671 struct scsi_device *sdev;
4672 int i;
4673
4674 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
4675 if (!sdev)
4676 return;
4677 if (!ioc->raid_data.pIocPg2)
4678 goto out;
4679 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
4680 goto out;
4681 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
4682 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
4683 goto release_sdev;
4684 out:
4685 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4686 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
4687 scsi_remove_device(sdev);
4688 release_sdev:
4689 scsi_device_put(sdev);
4690}
4691
0c33b27d
CH
4692static int
4693mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
4694{
4695 struct Scsi_Host *sh;
4696 MPT_SCSI_HOST *hd;
4697 MPT_ADAPTER *ioc;
4698 unsigned long flags;
1ca00bb7 4699 int ii;
0c33b27d
CH
4700 int numSGE = 0;
4701 int scale;
4702 int ioc_cap;
0c33b27d
CH
4703 int error=0;
4704 int r;
4705
4706 r = mpt_attach(pdev,id);
4707 if (r)
4708 return r;
4709
4710 ioc = pci_get_drvdata(pdev);
3eb0822c 4711 mptsas_fw_event_off(ioc);
0c33b27d
CH
4712 ioc->DoneCtx = mptsasDoneCtx;
4713 ioc->TaskCtx = mptsasTaskCtx;
4714 ioc->InternalCtx = mptsasInternalCtx;
4715
4716 /* Added sanity check on readiness of the MPT adapter.
4717 */
4718 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
4719 printk(MYIOC_s_WARN_FMT
4720 "Skipping because it's not operational!\n",
4721 ioc->name);
7acec1e7
MED
4722 error = -ENODEV;
4723 goto out_mptsas_probe;
0c33b27d
CH
4724 }
4725
4726 if (!ioc->active) {
4727 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
4728 ioc->name);
7acec1e7
MED
4729 error = -ENODEV;
4730 goto out_mptsas_probe;
0c33b27d
CH
4731 }
4732
4733 /* Sanity check - ensure at least 1 port is INITIATOR capable
4734 */
4735 ioc_cap = 0;
4736 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
4737 if (ioc->pfacts[ii].ProtocolFlags &
4738 MPI_PORTFACTS_PROTOCOL_INITIATOR)
4739 ioc_cap++;
4740 }
4741
4742 if (!ioc_cap) {
4743 printk(MYIOC_s_WARN_FMT
4744 "Skipping ioc=%p because SCSI Initiator mode "
4745 "is NOT enabled!\n", ioc->name, ioc);
466544d8 4746 return 0;
0c33b27d
CH
4747 }
4748
4749 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
4750 if (!sh) {
4751 printk(MYIOC_s_WARN_FMT
4752 "Unable to register controller with SCSI subsystem\n",
4753 ioc->name);
7acec1e7
MED
4754 error = -1;
4755 goto out_mptsas_probe;
0c33b27d
CH
4756 }
4757
4758 spin_lock_irqsave(&ioc->FreeQlock, flags);
4759
4760 /* Attach the SCSI Host to the IOC structure
4761 */
4762 ioc->sh = sh;
4763
4764 sh->io_port = 0;
4765 sh->n_io_port = 0;
4766 sh->irq = 0;
4767
4768 /* set 16 byte cdb's */
4769 sh->max_cmd_len = 16;
79a3ec1a
KD
4770 sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
4771 sh->max_id = -1;
793955f5 4772 sh->max_lun = max_lun;
0c33b27d
CH
4773 sh->transportt = mptsas_transport_template;
4774
0c33b27d
CH
4775 /* Required entry.
4776 */
4777 sh->unique_id = ioc->id;
4778
4779 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 4780 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 4781 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 4782 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 4783 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
4784
4785 /* Verify that we won't exceed the maximum
4786 * number of chain buffers
4787 * We can optimize: ZZ = req_sz/sizeof(SGE)
4788 * For 32bit SGE's:
4789 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
4790 * + (req_sz - 64)/sizeof(SGE)
4791 * A slightly different algorithm is required for
4792 * 64bit SGEs.
4793 */
14d0f0b0
KD
4794 scale = ioc->req_sz/ioc->SGE_size;
4795 if (ioc->sg_addr_size == sizeof(u64)) {
0c33b27d
CH
4796 numSGE = (scale - 1) *
4797 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 4798 (ioc->req_sz - 60) / ioc->SGE_size;
0c33b27d
CH
4799 } else {
4800 numSGE = 1 + (scale - 1) *
4801 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 4802 (ioc->req_sz - 64) / ioc->SGE_size;
0c33b27d
CH
4803 }
4804
4805 if (numSGE < sh->sg_tablesize) {
4806 /* Reset this value */
d6ecdd63 4807 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
4808 "Resetting sg_tablesize to %d from %d\n",
4809 ioc->name, numSGE, sh->sg_tablesize));
4810 sh->sg_tablesize = numSGE;
4811 }
4812
e7eae9f6 4813 hd = shost_priv(sh);
0c33b27d
CH
4814 hd->ioc = ioc;
4815
4816 /* SCSI needs scsi_cmnd lookup table!
4817 * (with size equal to req_depth*PtrSz!)
4818 */
e8206381
EM
4819 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
4820 if (!ioc->ScsiLookup) {
0c33b27d 4821 error = -ENOMEM;
bc6e089a 4822 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
7acec1e7 4823 goto out_mptsas_probe;
0c33b27d 4824 }
e8206381 4825 spin_lock_init(&ioc->scsi_lookup_lock);
0c33b27d 4826
d6ecdd63 4827 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
e8206381 4828 ioc->name, ioc->ScsiLookup));
0c33b27d 4829
0c33b27d
CH
4830 ioc->sas_data.ptClear = mpt_pt_clear;
4831
df9e062a
EM
4832 hd->last_queue_full = 0;
4833 INIT_LIST_HEAD(&hd->target_reset_list);
3eb0822c
KD
4834 INIT_LIST_HEAD(&ioc->sas_device_info_list);
4835 mutex_init(&ioc->sas_device_info_mutex);
4836
df9e062a
EM
4837 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4838
0c33b27d
CH
4839 if (ioc->sas_data.ptClear==1) {
4840 mptbase_sas_persist_operation(
4841 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
4842 }
4843
0c33b27d
CH
4844 error = scsi_add_host(sh, &ioc->pcidev->dev);
4845 if (error) {
29dd3609
EM
4846 dprintk(ioc, printk(MYIOC_s_ERR_FMT
4847 "scsi_add_host failed\n", ioc->name));
7acec1e7 4848 goto out_mptsas_probe;
0c33b27d
CH
4849 }
4850
eedf92b9
KD
4851 /* older firmware doesn't support expander events */
4852 if ((ioc->facts.HeaderVersion >> 8) < 0xE)
4853 ioc->old_sas_discovery_protocal = 1;
0c33b27d 4854 mptsas_scan_sas_topology(ioc);
3eb0822c 4855 mptsas_fw_event_on(ioc);
0c33b27d
CH
4856 return 0;
4857
547f9a21 4858 out_mptsas_probe:
0c33b27d
CH
4859
4860 mptscsih_remove(pdev);
4861 return error;
4862}
4863
7b5a65b9
KD
4864void
4865mptsas_shutdown(struct pci_dev *pdev)
4866{
4867 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4868
3eb0822c
KD
4869 mptsas_fw_event_off(ioc);
4870 mptsas_cleanup_fw_event_q(ioc);
7b5a65b9
KD
4871}
4872
0c33b27d
CH
4873static void __devexit mptsas_remove(struct pci_dev *pdev)
4874{
4875 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4876 struct mptsas_portinfo *p, *n;
547f9a21 4877 int i;
0c33b27d 4878
7b5a65b9
KD
4879 mptsas_shutdown(pdev);
4880
3eb0822c
KD
4881 mptsas_del_device_components(ioc);
4882
b506ade9 4883 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
4884 sas_remove_host(ioc->sh);
4885
9a28f49a 4886 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
4887 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
4888 list_del(&p->list);
547f9a21 4889 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 4890 mptsas_port_delete(ioc, p->phy_info[i].port_details);
3eb0822c 4891
547f9a21 4892 kfree(p->phy_info);
0c33b27d
CH
4893 kfree(p);
4894 }
9a28f49a 4895 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022 4896 ioc->hba_port_info = NULL;
0c33b27d
CH
4897 mptscsih_remove(pdev);
4898}
4899
4900static struct pci_device_id mptsas_pci_table[] = {
87cf8986 4901 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 4902 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4903 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 4904 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4905 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 4906 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4907 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 4908 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4909 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
4910 PCI_ANY_ID, PCI_ANY_ID },
4911 {0} /* Terminating entry */
4912};
4913MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
4914
4915
4916static struct pci_driver mptsas_driver = {
4917 .name = "mptsas",
4918 .id_table = mptsas_pci_table,
4919 .probe = mptsas_probe,
4920 .remove = __devexit_p(mptsas_remove),
7b5a65b9 4921 .shutdown = mptsas_shutdown,
0c33b27d
CH
4922#ifdef CONFIG_PM
4923 .suspend = mptscsih_suspend,
4924 .resume = mptscsih_resume,
4925#endif
4926};
4927
4928static int __init
4929mptsas_init(void)
4930{
57ce21bf
PS
4931 int error;
4932
0c33b27d
CH
4933 show_mptmod_ver(my_NAME, my_VERSION);
4934
4935 mptsas_transport_template =
4936 sas_attach_transport(&mptsas_transport_functions);
4937 if (!mptsas_transport_template)
4938 return -ENODEV;
4939
4940 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
e7deff33 4941 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d
CH
4942 mptsasInternalCtx =
4943 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 4944 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
e7deff33
KD
4945 mptsasDeviceResetCtx =
4946 mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d 4947
d6ecdd63
PS
4948 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
4949 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 4950
57ce21bf
PS
4951 error = pci_register_driver(&mptsas_driver);
4952 if (error)
4953 sas_release_transport(mptsas_transport_template);
4954
4955 return error;
0c33b27d
CH
4956}
4957
4958static void __exit
4959mptsas_exit(void)
4960{
4961 pci_unregister_driver(&mptsas_driver);
4962 sas_release_transport(mptsas_transport_template);
4963
4964 mpt_reset_deregister(mptsasDoneCtx);
4965 mpt_event_deregister(mptsasDoneCtx);
4966
da4fa655 4967 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
4968 mpt_deregister(mptsasInternalCtx);
4969 mpt_deregister(mptsasTaskCtx);
4970 mpt_deregister(mptsasDoneCtx);
e7deff33 4971 mpt_deregister(mptsasDeviceResetCtx);
0c33b27d
CH
4972}
4973
4974module_init(mptsas_init);
4975module_exit(mptsas_exit);