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