[SCSI] mpt fusion: Fix sparse warnings
[deliverable/linux.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 *
f36789e2 6 * Copyright (c) 1999-2007 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;
0c33b27d 96
b506ade9 97static void mptsas_hotplug_work(struct work_struct *work);
0c33b27d 98
d6ecdd63
PS
99static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
100 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
101{
29dd3609
EM
102 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
103 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
104 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
105 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
106 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
107 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
108 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
109 ioc->name, phy_data->Port));
110 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
111 ioc->name, phy_data->PortFlags));
112 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
113 ioc->name, phy_data->PhyFlags));
114 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
115 ioc->name, phy_data->NegotiatedLinkRate));
116 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
117 "Controller PHY Device Info=0x%X\n", ioc->name,
118 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
119 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
120 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
121}
122
d6ecdd63 123static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
124{
125 __le64 sas_address;
126
127 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
128
29dd3609
EM
129 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
130 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
131 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
132 "Attached Device Handle=0x%X\n", ioc->name,
133 le16_to_cpu(pg0->AttachedDevHandle)));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
135 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
137 "Attached PHY Identifier=0x%X\n", ioc->name,
138 pg0->AttachedPhyIdentifier));
139 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
140 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
141 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
142 ioc->name, pg0->ProgrammedLinkRate));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
144 ioc->name, pg0->ChangeCount));
145 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
146 ioc->name, le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
147}
148
d6ecdd63 149static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 150{
29dd3609
EM
151 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
152 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
153 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
154 ioc->name, pg1->InvalidDwordCount));
155 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
156 "Running Disparity Error Count=0x%x\n", ioc->name,
157 pg1->RunningDisparityErrorCount));
158 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
159 "Loss Dword Synch Count=0x%x\n", ioc->name,
160 pg1->LossDwordSynchCount));
161 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
162 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
163 pg1->PhyResetProblemCount));
b5141128
CH
164}
165
d6ecdd63 166static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
167{
168 __le64 sas_address;
169
170 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
171
29dd3609
EM
172 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
173 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
174 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
175 ioc->name, le16_to_cpu(pg0->DevHandle)));
176 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
177 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
178 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
179 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
180 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
181 ioc->name, le16_to_cpu(pg0->Slot)));
182 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
183 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
184 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
185 ioc->name, pg0->TargetID));
186 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
187 ioc->name, pg0->Bus));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
189 ioc->name, pg0->PhyNum));
190 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
191 ioc->name, le16_to_cpu(pg0->AccessStatus)));
192 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
193 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
194 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
195 ioc->name, le16_to_cpu(pg0->Flags)));
196 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
197 ioc->name, pg0->PhysicalPort));
b5141128
CH
198}
199
d6ecdd63
PS
200static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
201{
29dd3609
EM
202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
203 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
205 ioc->name, pg1->PhysicalPort));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
207 ioc->name, pg1->PhyIdentifier));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
209 ioc->name, pg1->NegotiatedLinkRate));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
211 ioc->name, pg1->ProgrammedLinkRate));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
213 ioc->name, pg1->HwLinkRate));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
215 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
217 "Attached Device Handle=0x%X\n\n", ioc->name,
218 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 219}
b5141128 220
e3094447
CH
221static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
222{
223 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
224 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
225}
226
227static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
228{
229 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
230 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
231}
232
e6b2d76a
ME
233/*
234 * mptsas_find_portinfo_by_handle
235 *
236 * This function should be called with the sas_topology_mutex already held
237 */
238static struct mptsas_portinfo *
239mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
240{
241 struct mptsas_portinfo *port_info, *rc=NULL;
242 int i;
243
244 list_for_each_entry(port_info, &ioc->sas_topology, list)
245 for (i = 0; i < port_info->num_phys; i++)
246 if (port_info->phy_info[i].identify.handle == handle) {
247 rc = port_info;
248 goto out;
249 }
250 out:
251 return rc;
252}
253
bd23e94c
ME
254/*
255 * Returns true if there is a scsi end device
256 */
257static inline int
258mptsas_is_end_device(struct mptsas_devinfo * attached)
259{
547f9a21 260 if ((attached->sas_address) &&
bd23e94c
ME
261 (attached->device_info &
262 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
263 ((attached->device_info &
264 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
265 (attached->device_info &
266 MPI_SAS_DEVICE_INFO_STP_TARGET) |
267 (attached->device_info &
268 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
269 return 1;
270 else
271 return 0;
272}
273
547f9a21 274/* no mutex */
376ac830 275static void
d6ecdd63 276mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
277{
278 struct mptsas_portinfo *port_info;
279 struct mptsas_phyinfo *phy_info;
280 u8 i;
281
282 if (!port_details)
283 return;
284
285 port_info = port_details->port_info;
286 phy_info = port_info->phy_info;
287
29dd3609
EM
288 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
289 "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details,
f99be43b
EM
290 port_details->num_phys, (unsigned long long)
291 port_details->phy_bitmask));
547f9a21
EM
292
293 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
294 if(phy_info->port_details != port_details)
295 continue;
296 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
297 phy_info->port_details = NULL;
298 }
299 kfree(port_details);
300}
301
302static inline struct sas_rphy *
303mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
304{
305 if (phy_info->port_details)
306 return phy_info->port_details->rphy;
307 else
308 return NULL;
309}
310
311static inline void
d6ecdd63 312mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
313{
314 if (phy_info->port_details) {
315 phy_info->port_details->rphy = rphy;
29dd3609
EM
316 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
317 ioc->name, rphy));
547f9a21
EM
318 }
319
547f9a21 320 if (rphy) {
29dd3609
EM
321 dsaswideprintk(ioc, dev_printk(MYIOC_s_DEBUG_FMT,
322 &rphy->dev, "add:", ioc->name));
323 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
324 ioc->name, rphy, rphy->dev.release));
547f9a21 325 }
547f9a21
EM
326}
327
328static inline struct sas_port *
329mptsas_get_port(struct mptsas_phyinfo *phy_info)
330{
331 if (phy_info->port_details)
332 return phy_info->port_details->port;
333 else
334 return NULL;
335}
336
337static inline void
d6ecdd63 338mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
339{
340 if (phy_info->port_details)
341 phy_info->port_details->port = port;
342
547f9a21 343 if (port) {
29dd3609
EM
344 dsaswideprintk(ioc, dev_printk(MYIOC_s_DEBUG_FMT,
345 &port->dev, "add:", ioc->name));
346 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
347 ioc->name, port, port->dev.release));
547f9a21 348 }
547f9a21
EM
349}
350
351static inline struct scsi_target *
352mptsas_get_starget(struct mptsas_phyinfo *phy_info)
353{
354 if (phy_info->port_details)
355 return phy_info->port_details->starget;
356 else
357 return NULL;
358}
359
360static inline void
361mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
362starget)
363{
364 if (phy_info->port_details)
365 phy_info->port_details->starget = starget;
366}
367
368
369/*
370 * mptsas_setup_wide_ports
371 *
372 * Updates for new and existing narrow/wide port configuration
373 * in the sas_topology
374 */
376ac830 375static void
547f9a21
EM
376mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
377{
378 struct mptsas_portinfo_details * port_details;
379 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
380 u64 sas_address;
381 int i, j;
382
383 mutex_lock(&ioc->sas_topology_mutex);
384
385 phy_info = port_info->phy_info;
386 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
387 if (phy_info->attached.handle)
388 continue;
389 port_details = phy_info->port_details;
390 if (!port_details)
391 continue;
392 if (port_details->num_phys < 2)
393 continue;
394 /*
395 * Removing a phy from a port, letting the last
396 * phy be removed by firmware events.
397 */
29dd3609
EM
398 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
399 "%s: [%p]: deleting phy = %d\n",
400 ioc->name, __FUNCTION__, port_details, i));
547f9a21
EM
401 port_details->num_phys--;
402 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
403 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
404 sas_port_delete_phy(port_details->port, phy_info->phy);
405 phy_info->port_details = NULL;
406 }
407
408 /*
409 * Populate and refresh the tree
410 */
411 phy_info = port_info->phy_info;
412 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
413 sas_address = phy_info->attached.sas_address;
29dd3609
EM
414 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
415 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
416 if (!sas_address)
417 continue;
418 port_details = phy_info->port_details;
419 /*
420 * Forming a port
421 */
422 if (!port_details) {
423 port_details = kzalloc(sizeof(*port_details),
424 GFP_KERNEL);
425 if (!port_details)
426 goto out;
427 port_details->num_phys = 1;
428 port_details->port_info = port_info;
547f9a21
EM
429 if (phy_info->phy_id < 64 )
430 port_details->phy_bitmask |=
431 (1 << phy_info->phy_id);
432 phy_info->sas_port_add_phy=1;
29dd3609 433 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
f99be43b 434 "phy_id=%d sas_address=0x%018llX\n",
29dd3609 435 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
436 phy_info->port_details = port_details;
437 }
438
439 if (i == port_info->num_phys - 1)
440 continue;
441 phy_info_cmp = &port_info->phy_info[i + 1];
442 for (j = i + 1 ; j < port_info->num_phys ; j++,
443 phy_info_cmp++) {
444 if (!phy_info_cmp->attached.sas_address)
445 continue;
446 if (sas_address != phy_info_cmp->attached.sas_address)
447 continue;
448 if (phy_info_cmp->port_details == port_details )
449 continue;
29dd3609 450 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 451 "\t\tphy_id=%d sas_address=0x%018llX\n",
29dd3609 452 ioc->name, j, (unsigned long long)
f99be43b 453 phy_info_cmp->attached.sas_address));
547f9a21
EM
454 if (phy_info_cmp->port_details) {
455 port_details->rphy =
456 mptsas_get_rphy(phy_info_cmp);
457 port_details->port =
458 mptsas_get_port(phy_info_cmp);
459 port_details->starget =
460 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
461 port_details->num_phys =
462 phy_info_cmp->port_details->num_phys;
547f9a21
EM
463 if (!phy_info_cmp->port_details->num_phys)
464 kfree(phy_info_cmp->port_details);
465 } else
466 phy_info_cmp->sas_port_add_phy=1;
467 /*
468 * Adding a phy to a port
469 */
470 phy_info_cmp->port_details = port_details;
471 if (phy_info_cmp->phy_id < 64 )
472 port_details->phy_bitmask |=
473 (1 << phy_info_cmp->phy_id);
474 port_details->num_phys++;
475 }
476 }
477
478 out:
479
547f9a21
EM
480 for (i = 0; i < port_info->num_phys; i++) {
481 port_details = port_info->phy_info[i].port_details;
482 if (!port_details)
483 continue;
29dd3609 484 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 485 "%s: [%p]: phy_id=%02d num_phys=%02d "
29dd3609 486 "bitmask=0x%016llX\n", ioc->name, __FUNCTION__,
f99be43b
EM
487 port_details, i, port_details->num_phys,
488 (unsigned long long)port_details->phy_bitmask));
29dd3609
EM
489 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
490 ioc->name, port_details->port, port_details->rphy));
547f9a21 491 }
29dd3609 492 dsaswideprintk(ioc, printk("\n"));
547f9a21
EM
493 mutex_unlock(&ioc->sas_topology_mutex);
494}
495
df9e062a
EM
496/**
497 * csmisas_find_vtarget
498 *
499 * @ioc
500 * @volume_id
501 * @volume_bus
502 *
503 **/
504static VirtTarget *
505mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
506{
507 struct scsi_device *sdev;
a69de507 508 VirtDevice *vdevice;
df9e062a
EM
509 VirtTarget *vtarget = NULL;
510
511 shost_for_each_device(sdev, ioc->sh) {
a69de507 512 if ((vdevice = sdev->hostdata) == NULL)
df9e062a 513 continue;
a69de507
EM
514 if (vdevice->vtarget->id == id &&
515 vdevice->vtarget->channel == channel)
516 vtarget = vdevice->vtarget;
df9e062a
EM
517 }
518 return vtarget;
519}
520
521/**
522 * mptsas_target_reset
523 *
524 * Issues TARGET_RESET to end device using handshaking method
525 *
526 * @ioc
527 * @channel
528 * @id
529 *
530 * Returns (1) success
531 * (0) failure
532 *
533 **/
534static int
535mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
536{
537 MPT_FRAME_HDR *mf;
538 SCSITaskMgmt_t *pScsiTm;
539
540 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
d6ecdd63 541 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
df9e062a
EM
542 ioc->name,__FUNCTION__, __LINE__));
543 return 0;
544 }
545
546 /* Format the Request
547 */
548 pScsiTm = (SCSITaskMgmt_t *) mf;
549 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
550 pScsiTm->TargetID = id;
551 pScsiTm->Bus = channel;
552 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
553 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
554 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
555
d6ecdd63 556 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 557
7a195f46 558 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
df9e062a
EM
559
560 return 1;
561}
562
563/**
564 * mptsas_target_reset_queue
565 *
566 * Receive request for TARGET_RESET after recieving an firmware
567 * event NOT_RESPONDING_EVENT, then put command in link list
568 * and queue if task_queue already in use.
569 *
570 * @ioc
571 * @sas_event_data
572 *
573 **/
547f9a21 574static void
df9e062a
EM
575mptsas_target_reset_queue(MPT_ADAPTER *ioc,
576 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 577{
e7eae9f6 578 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
579 VirtTarget *vtarget = NULL;
580 struct mptsas_target_reset_event *target_reset_list;
581 u8 id, channel;
547f9a21 582
df9e062a
EM
583 id = sas_event_data->TargetID;
584 channel = sas_event_data->Bus;
585
586 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
587 return;
588
589 vtarget->deleted = 1; /* block IO */
590
591 target_reset_list = kzalloc(sizeof(*target_reset_list),
592 GFP_ATOMIC);
593 if (!target_reset_list) {
d6ecdd63 594 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
df9e062a
EM
595 ioc->name,__FUNCTION__, __LINE__));
596 return;
597 }
598
599 memcpy(&target_reset_list->sas_event_data, sas_event_data,
600 sizeof(*sas_event_data));
601 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
602
603 if (hd->resetPending)
604 return;
605
606 if (mptsas_target_reset(ioc, channel, id)) {
607 target_reset_list->target_reset_issued = 1;
608 hd->resetPending = 1;
609 }
610}
611
612/**
613 * mptsas_dev_reset_complete
614 *
615 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
616 * enable work queue to finish off removing device from upper layers.
617 * then send next TARGET_RESET in the queue.
618 *
619 * @ioc
620 *
621 **/
622static void
623mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
624{
e7eae9f6 625 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
626 struct list_head *head = &hd->target_reset_list;
627 struct mptsas_target_reset_event *target_reset_list;
628 struct mptsas_hotplug_event *ev;
629 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
630 u8 id, channel;
631 __le64 sas_address;
632
633 if (list_empty(head))
634 return;
635
636 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
637
638 sas_event_data = &target_reset_list->sas_event_data;
639 id = sas_event_data->TargetID;
640 channel = sas_event_data->Bus;
641 hd->resetPending = 0;
642
643 /*
644 * retry target reset
645 */
646 if (!target_reset_list->target_reset_issued) {
647 if (mptsas_target_reset(ioc, channel, id)) {
648 target_reset_list->target_reset_issued = 1;
649 hd->resetPending = 1;
650 }
651 return;
652 }
653
654 /*
655 * enable work queue to remove device from upper layers
656 */
657 list_del(&target_reset_list->list);
658
659 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
660 if (!ev) {
d6ecdd63 661 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
df9e062a
EM
662 ioc->name,__FUNCTION__, __LINE__));
663 return;
664 }
665
666 INIT_WORK(&ev->work, mptsas_hotplug_work);
667 ev->ioc = ioc;
668 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
669 ev->parent_handle =
670 le16_to_cpu(sas_event_data->ParentDevHandle);
671 ev->channel = channel;
672 ev->id =id;
673 ev->phy_id = sas_event_data->PhyNum;
674 memcpy(&sas_address, &sas_event_data->SASAddress,
675 sizeof(__le64));
676 ev->sas_address = le64_to_cpu(sas_address);
677 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
678 ev->event_type = MPTSAS_DEL_DEVICE;
679 schedule_work(&ev->work);
680 kfree(target_reset_list);
681
682 /*
683 * issue target reset to next device in the queue
684 */
685
686 head = &hd->target_reset_list;
687 if (list_empty(head))
688 return;
689
690 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
691 list);
692
693 sas_event_data = &target_reset_list->sas_event_data;
694 id = sas_event_data->TargetID;
695 channel = sas_event_data->Bus;
696
697 if (mptsas_target_reset(ioc, channel, id)) {
698 target_reset_list->target_reset_issued = 1;
699 hd->resetPending = 1;
700 }
701}
702
703/**
704 * mptsas_taskmgmt_complete
705 *
706 * @ioc
707 * @mf
708 * @mr
709 *
710 **/
711static int
712mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
713{
714 mptsas_dev_reset_complete(ioc);
715 return mptscsih_taskmgmt_complete(ioc, mf, mr);
716}
717
718/**
719 * mptscsih_ioc_reset
720 *
721 * @ioc
722 * @reset_phase
723 *
724 **/
725static int
726mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
727{
ba76ef24 728 MPT_SCSI_HOST *hd;
df9e062a
EM
729 struct mptsas_target_reset_event *target_reset_list, *n;
730 int rc;
731
732 rc = mptscsih_ioc_reset(ioc, reset_phase);
733
734 if (ioc->bus_type != SAS)
735 goto out;
736
737 if (reset_phase != MPT_IOC_POST_RESET)
738 goto out;
739
ba76ef24
JL
740 if (!ioc->sh || !ioc->sh->hostdata)
741 goto out;
e7eae9f6 742 hd = shost_priv(ioc->sh);
ba76ef24 743 if (!hd->ioc)
df9e062a
EM
744 goto out;
745
746 if (list_empty(&hd->target_reset_list))
747 goto out;
748
749 /* flush the target_reset_list */
750 list_for_each_entry_safe(target_reset_list, n,
751 &hd->target_reset_list, list) {
752 list_del(&target_reset_list->list);
753 kfree(target_reset_list);
547f9a21 754 }
df9e062a
EM
755
756 out:
757 return rc;
547f9a21
EM
758}
759
e3094447 760static int
52435430 761mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
762 u32 form, u32 form_specific)
763{
764 ConfigExtendedPageHeader_t hdr;
765 CONFIGPARMS cfg;
766 SasEnclosurePage0_t *buffer;
767 dma_addr_t dma_handle;
768 int error;
769 __le64 le_identifier;
770
771 memset(&hdr, 0, sizeof(hdr));
772 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
773 hdr.PageNumber = 0;
774 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
775 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
776
777 cfg.cfghdr.ehdr = &hdr;
778 cfg.physAddr = -1;
779 cfg.pageAddr = form + form_specific;
780 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
781 cfg.dir = 0; /* read */
782 cfg.timeout = 10;
783
784 error = mpt_config(ioc, &cfg);
785 if (error)
786 goto out;
787 if (!hdr.ExtPageLength) {
788 error = -ENXIO;
789 goto out;
790 }
791
792 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
793 &dma_handle);
794 if (!buffer) {
795 error = -ENOMEM;
796 goto out;
797 }
798
799 cfg.physAddr = dma_handle;
800 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
801
802 error = mpt_config(ioc, &cfg);
803 if (error)
804 goto out_free_consistent;
805
806 /* save config data */
807 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
808 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
809 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
810 enclosure->flags = le16_to_cpu(buffer->Flags);
811 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
812 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
813 enclosure->start_id = buffer->StartTargetID;
814 enclosure->start_channel = buffer->StartBus;
815 enclosure->sep_id = buffer->SEPTargetID;
816 enclosure->sep_channel = buffer->SEPBus;
817
818 out_free_consistent:
819 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
820 buffer, dma_handle);
821 out:
822 return error;
823}
b5141128 824
f013db32
JB
825static int
826mptsas_slave_configure(struct scsi_device *sdev)
827{
3c0c25b9 828
e8bf3941
JB
829 if (sdev->channel == MPTSAS_RAID_CHANNEL)
830 goto out;
831
832 sas_read_port_mode_page(sdev);
f013db32 833
e8bf3941 834 out:
f013db32
JB
835 return mptscsih_slave_configure(sdev);
836}
837
547f9a21
EM
838static int
839mptsas_target_alloc(struct scsi_target *starget)
840{
841 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 842 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21 843 VirtTarget *vtarget;
793955f5 844 u8 id, channel;
547f9a21
EM
845 struct sas_rphy *rphy;
846 struct mptsas_portinfo *p;
847 int i;
e80b002b 848 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
849
850 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
851 if (!vtarget)
852 return -ENOMEM;
853
854 vtarget->starget = starget;
e80b002b 855 vtarget->ioc_id = ioc->id;
793955f5
EM
856 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
857 id = starget->id;
547f9a21
EM
858 channel = 0;
859
793955f5
EM
860 /*
861 * RAID volumes placed beyond the last expected port.
862 */
863 if (starget->channel == MPTSAS_RAID_CHANNEL) {
e80b002b
EM
864 for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
865 if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
866 channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
547f9a21 867 goto out;
793955f5 868 }
547f9a21
EM
869
870 rphy = dev_to_rphy(starget->dev.parent);
e80b002b
EM
871 mutex_lock(&ioc->sas_topology_mutex);
872 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
873 for (i = 0; i < p->num_phys; i++) {
874 if (p->phy_info[i].attached.sas_address !=
875 rphy->identify.sas_address)
876 continue;
793955f5 877 id = p->phy_info[i].attached.id;
547f9a21
EM
878 channel = p->phy_info[i].attached.channel;
879 mptsas_set_starget(&p->phy_info[i], starget);
880
881 /*
882 * Exposing hidden raid components
883 */
e80b002b
EM
884 if (mptscsih_is_phys_disk(ioc, channel, id)) {
885 id = mptscsih_raid_id_to_num(ioc,
793955f5 886 channel, id);
547f9a21
EM
887 vtarget->tflags |=
888 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 889 p->phy_info[i].attached.phys_disk_num = id;
547f9a21 890 }
e80b002b 891 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
892 goto out;
893 }
894 }
e80b002b 895 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
896
897 kfree(vtarget);
898 return -ENXIO;
899
900 out:
793955f5
EM
901 vtarget->id = id;
902 vtarget->channel = channel;
547f9a21
EM
903 starget->hostdata = vtarget;
904 return 0;
905}
906
907static void
908mptsas_target_destroy(struct scsi_target *starget)
909{
910 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 911 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21
EM
912 struct sas_rphy *rphy;
913 struct mptsas_portinfo *p;
914 int i;
e80b002b 915 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
916
917 if (!starget->hostdata)
918 return;
919
e8bf3941 920 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
921 goto out;
922
923 rphy = dev_to_rphy(starget->dev.parent);
e80b002b 924 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
925 for (i = 0; i < p->num_phys; i++) {
926 if (p->phy_info[i].attached.sas_address !=
927 rphy->identify.sas_address)
928 continue;
929 mptsas_set_starget(&p->phy_info[i], NULL);
930 goto out;
931 }
932 }
933
934 out:
935 kfree(starget->hostdata);
936 starget->hostdata = NULL;
937}
938
939
0c33b27d 940static int
c7c82987 941mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 942{
c7c82987 943 struct Scsi_Host *host = sdev->host;
e7eae9f6 944 MPT_SCSI_HOST *hd = shost_priv(host);
0c33b27d
CH
945 struct sas_rphy *rphy;
946 struct mptsas_portinfo *p;
a69de507 947 VirtDevice *vdevice;
c7c82987 948 struct scsi_target *starget;
547f9a21 949 int i;
e80b002b 950 MPT_ADAPTER *ioc = hd->ioc;
0c33b27d 951
a69de507
EM
952 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
953 if (!vdevice) {
547f9a21 954 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
e80b002b 955 ioc->name, sizeof(VirtDevice));
0c33b27d
CH
956 return -ENOMEM;
957 }
c7c82987 958 starget = scsi_target(sdev);
a69de507 959 vdevice->vtarget = starget->hostdata;
0c33b27d 960
e8bf3941 961 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 962 goto out;
816aa907 963
c7c82987 964 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
e80b002b
EM
965 mutex_lock(&ioc->sas_topology_mutex);
966 list_for_each_entry(p, &ioc->sas_topology, list) {
0c33b27d 967 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
968 if (p->phy_info[i].attached.sas_address !=
969 rphy->identify.sas_address)
970 continue;
a69de507 971 vdevice->lun = sdev->lun;
547f9a21
EM
972 /*
973 * Exposing hidden raid components
974 */
e80b002b 975 if (mptscsih_is_phys_disk(ioc,
793955f5
EM
976 p->phy_info[i].attached.channel,
977 p->phy_info[i].attached.id))
547f9a21 978 sdev->no_uld_attach = 1;
e80b002b 979 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21 980 goto out;
0c33b27d
CH
981 }
982 }
e80b002b 983 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 984
a69de507 985 kfree(vdevice);
23f236ed 986 return -ENXIO;
0c33b27d
CH
987
988 out:
a69de507
EM
989 vdevice->vtarget->num_luns++;
990 sdev->hostdata = vdevice;
0c33b27d
CH
991 return 0;
992}
993
547f9a21
EM
994static int
995mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 996{
a69de507 997 VirtDevice *vdevice = SCpnt->device->hostdata;
7d3eecf7 998
a69de507 999 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
547f9a21
EM
1000 SCpnt->result = DID_NO_CONNECT << 16;
1001 done(SCpnt);
1002 return 0;
7d3eecf7 1003 }
547f9a21 1004
793955f5
EM
1005// scsi_print_command(SCpnt);
1006
547f9a21 1007 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1008}
1009
547f9a21 1010
0c33b27d 1011static struct scsi_host_template mptsas_driver_template = {
f78496da 1012 .module = THIS_MODULE,
0c33b27d
CH
1013 .proc_name = "mptsas",
1014 .proc_info = mptscsih_proc_info,
1015 .name = "MPT SPI Host",
1016 .info = mptscsih_info,
547f9a21
EM
1017 .queuecommand = mptsas_qcmd,
1018 .target_alloc = mptsas_target_alloc,
0c33b27d 1019 .slave_alloc = mptsas_slave_alloc,
f013db32 1020 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1021 .target_destroy = mptsas_target_destroy,
1022 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1023 .change_queue_depth = mptscsih_change_queue_depth,
1024 .eh_abort_handler = mptscsih_abort,
1025 .eh_device_reset_handler = mptscsih_dev_reset,
1026 .eh_bus_reset_handler = mptscsih_bus_reset,
1027 .eh_host_reset_handler = mptscsih_host_reset,
1028 .bios_param = mptscsih_bios_param,
1029 .can_queue = MPT_FC_CAN_QUEUE,
1030 .this_id = -1,
1031 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1032 .max_sectors = 8192,
1033 .cmd_per_lun = 7,
1034 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1035 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1036};
1037
b5141128 1038static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1039{
b5141128
CH
1040 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1041 ConfigExtendedPageHeader_t hdr;
1042 CONFIGPARMS cfg;
1043 SasPhyPage1_t *buffer;
1044 dma_addr_t dma_handle;
1045 int error;
0c33b27d 1046
f4ad7b58
JB
1047 /* FIXME: only have link errors on local phys */
1048 if (!scsi_is_sas_phy_local(phy))
1049 return -EINVAL;
1050
b5141128
CH
1051 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1052 hdr.ExtPageLength = 0;
1053 hdr.PageNumber = 1 /* page number 1*/;
1054 hdr.Reserved1 = 0;
1055 hdr.Reserved2 = 0;
1056 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1057 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 1058
b5141128
CH
1059 cfg.cfghdr.ehdr = &hdr;
1060 cfg.physAddr = -1;
1061 cfg.pageAddr = phy->identify.phy_identifier;
1062 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1063 cfg.dir = 0; /* read */
1064 cfg.timeout = 10;
0c33b27d 1065
b5141128
CH
1066 error = mpt_config(ioc, &cfg);
1067 if (error)
1068 return error;
1069 if (!hdr.ExtPageLength)
1070 return -ENXIO;
0c33b27d 1071
b5141128
CH
1072 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1073 &dma_handle);
1074 if (!buffer)
1075 return -ENOMEM;
0c33b27d 1076
b5141128
CH
1077 cfg.physAddr = dma_handle;
1078 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1079
1080 error = mpt_config(ioc, &cfg);
1081 if (error)
1082 goto out_free_consistent;
1083
d6ecdd63 1084 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
1085
1086 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1087 phy->running_disparity_error_count =
1088 le32_to_cpu(buffer->RunningDisparityErrorCount);
1089 phy->loss_of_dword_sync_count =
1090 le32_to_cpu(buffer->LossDwordSynchCount);
1091 phy->phy_reset_problem_count =
1092 le32_to_cpu(buffer->PhyResetProblemCount);
1093
1094 out_free_consistent:
1095 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1096 buffer, dma_handle);
1097 return error;
0c33b27d
CH
1098}
1099
da4fa655
CH
1100static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1101 MPT_FRAME_HDR *reply)
1102{
1103 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
1104 if (reply != NULL) {
1105 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
1106 memcpy(ioc->sas_mgmt.reply, reply,
1107 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1108 }
1109 complete(&ioc->sas_mgmt.done);
1110 return 1;
1111}
1112
1113static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1114{
1115 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1116 SasIoUnitControlRequest_t *req;
1117 SasIoUnitControlReply_t *reply;
1118 MPT_FRAME_HDR *mf;
1119 MPIHeader_t *hdr;
1120 unsigned long timeleft;
1121 int error = -ERESTARTSYS;
1122
f4ad7b58
JB
1123 /* FIXME: fusion doesn't allow non-local phy reset */
1124 if (!scsi_is_sas_phy_local(phy))
1125 return -EINVAL;
1126
da4fa655
CH
1127 /* not implemented for expanders */
1128 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1129 return -ENXIO;
1130
eeb846ce 1131 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
1132 goto out;
1133
1134 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1135 if (!mf) {
1136 error = -ENOMEM;
1137 goto out_unlock;
1138 }
1139
1140 hdr = (MPIHeader_t *) mf;
1141 req = (SasIoUnitControlRequest_t *)mf;
1142 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1143 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1144 req->MsgContext = hdr->MsgContext;
1145 req->Operation = hard_reset ?
1146 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1147 req->PhyNum = phy->identify.phy_identifier;
1148
1149 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1150
1151 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1152 10 * HZ);
1153 if (!timeleft) {
1154 /* On timeout reset the board */
1155 mpt_free_msg_frame(ioc, mf);
1156 mpt_HardResetHandler(ioc, CAN_SLEEP);
1157 error = -ETIMEDOUT;
1158 goto out_unlock;
1159 }
1160
1161 /* a reply frame is expected */
1162 if ((ioc->sas_mgmt.status &
1163 MPT_IOCTL_STATUS_RF_VALID) == 0) {
1164 error = -ENXIO;
1165 goto out_unlock;
1166 }
1167
1168 /* process the completed Reply Message Frame */
1169 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1170 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
29dd3609
EM
1171 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
1172 ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);
da4fa655
CH
1173 error = -ENXIO;
1174 goto out_unlock;
1175 }
1176
1177 error = 0;
1178
1179 out_unlock:
eeb846ce 1180 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
1181 out:
1182 return error;
1183}
0c33b27d 1184
e3094447
CH
1185static int
1186mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1187{
1188 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1189 int i, error;
1190 struct mptsas_portinfo *p;
1191 struct mptsas_enclosure enclosure_info;
1192 u64 enclosure_handle;
1193
1194 mutex_lock(&ioc->sas_topology_mutex);
1195 list_for_each_entry(p, &ioc->sas_topology, list) {
1196 for (i = 0; i < p->num_phys; i++) {
1197 if (p->phy_info[i].attached.sas_address ==
1198 rphy->identify.sas_address) {
1199 enclosure_handle = p->phy_info[i].
1200 attached.handle_enclosure;
1201 goto found_info;
1202 }
1203 }
1204 }
1205 mutex_unlock(&ioc->sas_topology_mutex);
1206 return -ENXIO;
1207
1208 found_info:
1209 mutex_unlock(&ioc->sas_topology_mutex);
1210 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 1211 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
1212 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1213 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1214 if (!error)
1215 *identifier = enclosure_info.enclosure_logical_id;
1216 return error;
1217}
1218
1219static int
1220mptsas_get_bay_identifier(struct sas_rphy *rphy)
1221{
1222 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1223 struct mptsas_portinfo *p;
1224 int i, rc;
1225
1226 mutex_lock(&ioc->sas_topology_mutex);
1227 list_for_each_entry(p, &ioc->sas_topology, list) {
1228 for (i = 0; i < p->num_phys; i++) {
1229 if (p->phy_info[i].attached.sas_address ==
1230 rphy->identify.sas_address) {
1231 rc = p->phy_info[i].attached.slot;
1232 goto out;
1233 }
1234 }
1235 }
1236 rc = -ENXIO;
1237 out:
1238 mutex_unlock(&ioc->sas_topology_mutex);
1239 return rc;
1240}
1241
159e36fe
FT
1242static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1243 struct request *req)
1244{
1245 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
1246 MPT_FRAME_HDR *mf;
1247 SmpPassthroughRequest_t *smpreq;
1248 struct request *rsp = req->next_rq;
1249 int ret;
1250 int flagsLength;
1251 unsigned long timeleft;
1252 char *psge;
1253 dma_addr_t dma_addr_in = 0;
1254 dma_addr_t dma_addr_out = 0;
1255 u64 sas_address = 0;
1256
1257 if (!rsp) {
29dd3609
EM
1258 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
1259 ioc->name, __FUNCTION__);
159e36fe
FT
1260 return -EINVAL;
1261 }
1262
1263 /* do we need to support multiple segments? */
1264 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
29dd3609
EM
1265 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
1266 ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len,
1267 rsp->bio->bi_vcnt, rsp->data_len);
159e36fe
FT
1268 return -EINVAL;
1269 }
1270
1271 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
1272 if (ret)
1273 goto out;
1274
1275 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1276 if (!mf) {
1277 ret = -ENOMEM;
1278 goto out_unlock;
1279 }
1280
1281 smpreq = (SmpPassthroughRequest_t *)mf;
1282 memset(smpreq, 0, sizeof(*smpreq));
1283
1284 smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
1285 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
1286
1287 if (rphy)
1288 sas_address = rphy->identify.sas_address;
1289 else {
1290 struct mptsas_portinfo *port_info;
1291
1292 mutex_lock(&ioc->sas_topology_mutex);
1293 port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
1294 if (port_info && port_info->phy_info)
1295 sas_address =
1296 port_info->phy_info[0].phy->identify.sas_address;
1297 mutex_unlock(&ioc->sas_topology_mutex);
1298 }
1299
1300 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
1301
1302 psge = (char *)
1303 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
1304
1305 /* request */
1306 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1307 MPI_SGE_FLAGS_END_OF_BUFFER |
1308 MPI_SGE_FLAGS_DIRECTION |
1309 mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
1310 flagsLength |= (req->data_len - 4);
1311
1312 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
1313 req->data_len, PCI_DMA_BIDIRECTIONAL);
1314 if (!dma_addr_out)
1315 goto put_mf;
1316 mpt_add_sge(psge, flagsLength, dma_addr_out);
1317 psge += (sizeof(u32) + sizeof(dma_addr_t));
1318
1319 /* response */
1320 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
1321 flagsLength |= rsp->data_len + 4;
1322 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
1323 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1324 if (!dma_addr_in)
1325 goto unmap;
1326 mpt_add_sge(psge, flagsLength, dma_addr_in);
1327
1328 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1329
1330 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
1331 if (!timeleft) {
29dd3609 1332 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);
159e36fe
FT
1333 /* On timeout reset the board */
1334 mpt_HardResetHandler(ioc, CAN_SLEEP);
1335 ret = -ETIMEDOUT;
1336 goto unmap;
1337 }
1338 mf = NULL;
1339
1340 if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
1341 SmpPassthroughReply_t *smprep;
1342
1343 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
1344 memcpy(req->sense, smprep, sizeof(*smprep));
1345 req->sense_len = sizeof(*smprep);
1346 } else {
29dd3609
EM
1347 printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
1348 ioc->name, __FUNCTION__);
159e36fe
FT
1349 ret = -ENXIO;
1350 }
1351unmap:
1352 if (dma_addr_out)
1353 pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
1354 PCI_DMA_BIDIRECTIONAL);
1355 if (dma_addr_in)
1356 pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
1357 PCI_DMA_BIDIRECTIONAL);
1358put_mf:
1359 if (mf)
1360 mpt_free_msg_frame(ioc, mf);
1361out_unlock:
1362 mutex_unlock(&ioc->sas_mgmt.mutex);
1363out:
1364 return ret;
1365}
1366
b5141128
CH
1367static struct sas_function_template mptsas_transport_functions = {
1368 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
1369 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1370 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 1371 .phy_reset = mptsas_phy_reset,
159e36fe 1372 .smp_handler = mptsas_smp_handler,
b5141128
CH
1373};
1374
1375static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
1376
1377static int
1378mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1379{
1380 ConfigExtendedPageHeader_t hdr;
1381 CONFIGPARMS cfg;
1382 SasIOUnitPage0_t *buffer;
1383 dma_addr_t dma_handle;
1384 int error, i;
1385
1386 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1387 hdr.ExtPageLength = 0;
1388 hdr.PageNumber = 0;
1389 hdr.Reserved1 = 0;
1390 hdr.Reserved2 = 0;
1391 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1392 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1393
1394 cfg.cfghdr.ehdr = &hdr;
1395 cfg.physAddr = -1;
1396 cfg.pageAddr = 0;
1397 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1398 cfg.dir = 0; /* read */
1399 cfg.timeout = 10;
1400
1401 error = mpt_config(ioc, &cfg);
1402 if (error)
1403 goto out;
1404 if (!hdr.ExtPageLength) {
1405 error = -ENXIO;
1406 goto out;
1407 }
1408
1409 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1410 &dma_handle);
1411 if (!buffer) {
1412 error = -ENOMEM;
1413 goto out;
1414 }
1415
1416 cfg.physAddr = dma_handle;
1417 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1418
1419 error = mpt_config(ioc, &cfg);
1420 if (error)
1421 goto out_free_consistent;
1422
1423 port_info->num_phys = buffer->NumPhys;
1424 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1425 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1426 if (!port_info->phy_info) {
1427 error = -ENOMEM;
1428 goto out_free_consistent;
1429 }
1430
edb9068d
PS
1431 ioc->nvdata_version_persistent =
1432 le16_to_cpu(buffer->NvdataVersionPersistent);
1433 ioc->nvdata_version_default =
1434 le16_to_cpu(buffer->NvdataVersionDefault);
1435
0c33b27d 1436 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 1437 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
1438 port_info->phy_info[i].phy_id = i;
1439 port_info->phy_info[i].port_id =
1440 buffer->PhyData[i].Port;
1441 port_info->phy_info[i].negotiated_link_rate =
1442 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 1443 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
1444 port_info->phy_info[i].handle =
1445 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
1446 }
1447
1448 out_free_consistent:
1449 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1450 buffer, dma_handle);
1451 out:
1452 return error;
1453}
1454
edb9068d
PS
1455static int
1456mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
1457{
1458 ConfigExtendedPageHeader_t hdr;
1459 CONFIGPARMS cfg;
1460 SasIOUnitPage1_t *buffer;
1461 dma_addr_t dma_handle;
1462 int error;
1463 u16 device_missing_delay;
1464
1465 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
1466 memset(&cfg, 0, sizeof(CONFIGPARMS));
1467
1468 cfg.cfghdr.ehdr = &hdr;
1469 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1470 cfg.timeout = 10;
1471 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1472 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1473 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
1474 cfg.cfghdr.ehdr->PageNumber = 1;
1475
1476 error = mpt_config(ioc, &cfg);
1477 if (error)
1478 goto out;
1479 if (!hdr.ExtPageLength) {
1480 error = -ENXIO;
1481 goto out;
1482 }
1483
1484 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1485 &dma_handle);
1486 if (!buffer) {
1487 error = -ENOMEM;
1488 goto out;
1489 }
1490
1491 cfg.physAddr = dma_handle;
1492 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1493
1494 error = mpt_config(ioc, &cfg);
1495 if (error)
1496 goto out_free_consistent;
1497
1498 ioc->io_missing_delay =
1499 le16_to_cpu(buffer->IODeviceMissingDelay);
1500 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
1501 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
1502 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
1503 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1504
1505 out_free_consistent:
1506 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1507 buffer, dma_handle);
1508 out:
1509 return error;
1510}
1511
0c33b27d
CH
1512static int
1513mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1514 u32 form, u32 form_specific)
1515{
1516 ConfigExtendedPageHeader_t hdr;
1517 CONFIGPARMS cfg;
1518 SasPhyPage0_t *buffer;
1519 dma_addr_t dma_handle;
1520 int error;
1521
1522 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1523 hdr.ExtPageLength = 0;
1524 hdr.PageNumber = 0;
1525 hdr.Reserved1 = 0;
1526 hdr.Reserved2 = 0;
1527 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1528 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1529
1530 cfg.cfghdr.ehdr = &hdr;
1531 cfg.dir = 0; /* read */
1532 cfg.timeout = 10;
1533
1534 /* Get Phy Pg 0 for each Phy. */
1535 cfg.physAddr = -1;
1536 cfg.pageAddr = form + form_specific;
1537 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1538
1539 error = mpt_config(ioc, &cfg);
1540 if (error)
1541 goto out;
1542
1543 if (!hdr.ExtPageLength) {
1544 error = -ENXIO;
1545 goto out;
1546 }
1547
1548 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1549 &dma_handle);
1550 if (!buffer) {
1551 error = -ENOMEM;
1552 goto out;
1553 }
1554
1555 cfg.physAddr = dma_handle;
1556 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1557
1558 error = mpt_config(ioc, &cfg);
1559 if (error)
1560 goto out_free_consistent;
1561
d6ecdd63 1562 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
1563
1564 phy_info->hw_link_rate = buffer->HwLinkRate;
1565 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1566 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1567 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1568
1569 out_free_consistent:
1570 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1571 buffer, dma_handle);
1572 out:
1573 return error;
1574}
1575
1576static int
1577mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1578 u32 form, u32 form_specific)
1579{
1580 ConfigExtendedPageHeader_t hdr;
1581 CONFIGPARMS cfg;
1582 SasDevicePage0_t *buffer;
1583 dma_addr_t dma_handle;
1584 __le64 sas_address;
bd23e94c
ME
1585 int error=0;
1586
1587 if (ioc->sas_discovery_runtime &&
1588 mptsas_is_end_device(device_info))
1589 goto out;
0c33b27d
CH
1590
1591 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1592 hdr.ExtPageLength = 0;
1593 hdr.PageNumber = 0;
1594 hdr.Reserved1 = 0;
1595 hdr.Reserved2 = 0;
1596 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1597 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1598
1599 cfg.cfghdr.ehdr = &hdr;
1600 cfg.pageAddr = form + form_specific;
1601 cfg.physAddr = -1;
1602 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1603 cfg.dir = 0; /* read */
1604 cfg.timeout = 10;
1605
db9c9174 1606 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
1607 error = mpt_config(ioc, &cfg);
1608 if (error)
1609 goto out;
1610 if (!hdr.ExtPageLength) {
1611 error = -ENXIO;
1612 goto out;
1613 }
1614
1615 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1616 &dma_handle);
1617 if (!buffer) {
1618 error = -ENOMEM;
1619 goto out;
1620 }
1621
1622 cfg.physAddr = dma_handle;
1623 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1624
1625 error = mpt_config(ioc, &cfg);
1626 if (error)
1627 goto out_free_consistent;
1628
d6ecdd63 1629 mptsas_print_device_pg0(ioc, buffer);
0c33b27d
CH
1630
1631 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 1632 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
1633 device_info->handle_enclosure =
1634 le16_to_cpu(buffer->EnclosureHandle);
1635 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
1636 device_info->phy_id = buffer->PhyNum;
1637 device_info->port_id = buffer->PhysicalPort;
9a28f49a 1638 device_info->id = buffer->TargetID;
b506ade9 1639 device_info->phys_disk_num = ~0;
9a28f49a 1640 device_info->channel = buffer->Bus;
0c33b27d
CH
1641 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1642 device_info->sas_address = le64_to_cpu(sas_address);
1643 device_info->device_info =
1644 le32_to_cpu(buffer->DeviceInfo);
1645
1646 out_free_consistent:
1647 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1648 buffer, dma_handle);
1649 out:
1650 return error;
1651}
1652
1653static int
1654mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1655 u32 form, u32 form_specific)
1656{
1657 ConfigExtendedPageHeader_t hdr;
1658 CONFIGPARMS cfg;
1659 SasExpanderPage0_t *buffer;
1660 dma_addr_t dma_handle;
547f9a21 1661 int i, error;
0c33b27d
CH
1662
1663 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1664 hdr.ExtPageLength = 0;
1665 hdr.PageNumber = 0;
1666 hdr.Reserved1 = 0;
1667 hdr.Reserved2 = 0;
1668 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1669 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1670
1671 cfg.cfghdr.ehdr = &hdr;
1672 cfg.physAddr = -1;
1673 cfg.pageAddr = form + form_specific;
1674 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1675 cfg.dir = 0; /* read */
1676 cfg.timeout = 10;
1677
db9c9174 1678 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
1679 error = mpt_config(ioc, &cfg);
1680 if (error)
1681 goto out;
1682
1683 if (!hdr.ExtPageLength) {
1684 error = -ENXIO;
1685 goto out;
1686 }
1687
1688 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1689 &dma_handle);
1690 if (!buffer) {
1691 error = -ENOMEM;
1692 goto out;
1693 }
1694
1695 cfg.physAddr = dma_handle;
1696 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1697
1698 error = mpt_config(ioc, &cfg);
1699 if (error)
1700 goto out_free_consistent;
1701
1702 /* save config data */
1703 port_info->num_phys = buffer->NumPhys;
0c33b27d 1704 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1705 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1706 if (!port_info->phy_info) {
1707 error = -ENOMEM;
1708 goto out_free_consistent;
1709 }
1710
2ecce492 1711 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 1712 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
1713 port_info->phy_info[i].handle =
1714 le16_to_cpu(buffer->DevHandle);
1715 }
547f9a21 1716
0c33b27d
CH
1717 out_free_consistent:
1718 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1719 buffer, dma_handle);
1720 out:
1721 return error;
1722}
1723
1724static int
1725mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1726 u32 form, u32 form_specific)
1727{
1728 ConfigExtendedPageHeader_t hdr;
1729 CONFIGPARMS cfg;
1730 SasExpanderPage1_t *buffer;
1731 dma_addr_t dma_handle;
bd23e94c
ME
1732 int error=0;
1733
1734 if (ioc->sas_discovery_runtime &&
1735 mptsas_is_end_device(&phy_info->attached))
1736 goto out;
0c33b27d
CH
1737
1738 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1739 hdr.ExtPageLength = 0;
1740 hdr.PageNumber = 1;
1741 hdr.Reserved1 = 0;
1742 hdr.Reserved2 = 0;
1743 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1744 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1745
1746 cfg.cfghdr.ehdr = &hdr;
1747 cfg.physAddr = -1;
1748 cfg.pageAddr = form + form_specific;
1749 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1750 cfg.dir = 0; /* read */
1751 cfg.timeout = 10;
1752
1753 error = mpt_config(ioc, &cfg);
1754 if (error)
1755 goto out;
1756
1757 if (!hdr.ExtPageLength) {
1758 error = -ENXIO;
1759 goto out;
1760 }
1761
1762 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1763 &dma_handle);
1764 if (!buffer) {
1765 error = -ENOMEM;
1766 goto out;
1767 }
1768
1769 cfg.physAddr = dma_handle;
1770 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1771
1772 error = mpt_config(ioc, &cfg);
1773 if (error)
1774 goto out_free_consistent;
1775
1776
d6ecdd63 1777 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
1778
1779 /* save config data */
024358ee 1780 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
1781 phy_info->port_id = buffer->PhysicalPort;
1782 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1783 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1784 phy_info->hw_link_rate = buffer->HwLinkRate;
1785 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1786 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1787
0c33b27d
CH
1788 out_free_consistent:
1789 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1790 buffer, dma_handle);
1791 out:
1792 return error;
1793}
1794
1795static void
1796mptsas_parse_device_info(struct sas_identify *identify,
1797 struct mptsas_devinfo *device_info)
1798{
1799 u16 protocols;
1800
1801 identify->sas_address = device_info->sas_address;
1802 identify->phy_identifier = device_info->phy_id;
1803
1804 /*
1805 * Fill in Phy Initiator Port Protocol.
1806 * Bits 6:3, more than one bit can be set, fall through cases.
1807 */
1808 protocols = device_info->device_info & 0x78;
1809 identify->initiator_port_protocols = 0;
1810 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1811 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1812 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1813 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1814 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1815 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1816 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1817 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1818
1819 /*
1820 * Fill in Phy Target Port Protocol.
1821 * Bits 10:7, more than one bit can be set, fall through cases.
1822 */
1823 protocols = device_info->device_info & 0x780;
1824 identify->target_port_protocols = 0;
1825 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1826 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1827 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1828 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1829 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1830 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1831 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1832 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1833
1834 /*
1835 * Fill in Attached device type.
1836 */
1837 switch (device_info->device_info &
1838 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1839 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1840 identify->device_type = SAS_PHY_UNUSED;
1841 break;
1842 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1843 identify->device_type = SAS_END_DEVICE;
1844 break;
1845 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1846 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1847 break;
1848 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1849 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1850 break;
1851 }
1852}
1853
1854static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 1855 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 1856{
e6b2d76a 1857 MPT_ADAPTER *ioc;
9a28f49a 1858 struct sas_phy *phy;
547f9a21
EM
1859 struct sas_port *port;
1860 int error = 0;
0c33b27d 1861
547f9a21
EM
1862 if (!dev) {
1863 error = -ENODEV;
1864 goto out;
1865 }
e6b2d76a
ME
1866
1867 if (!phy_info->phy) {
1868 phy = sas_phy_alloc(dev, index);
547f9a21
EM
1869 if (!phy) {
1870 error = -ENOMEM;
1871 goto out;
1872 }
e6b2d76a
ME
1873 } else
1874 phy = phy_info->phy;
0c33b27d 1875
9a28f49a 1876 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
1877
1878 /*
1879 * Set Negotiated link rate.
1880 */
1881 switch (phy_info->negotiated_link_rate) {
1882 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 1883 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
1884 break;
1885 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 1886 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
1887 break;
1888 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 1889 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1890 break;
1891 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 1892 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1893 break;
1894 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1895 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1896 default:
9a28f49a 1897 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
1898 break;
1899 }
1900
1901 /*
1902 * Set Max hardware link rate.
1903 */
1904 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1905 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 1906 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1907 break;
1908 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1909 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1910 break;
1911 default:
1912 break;
1913 }
1914
1915 /*
1916 * Set Max programmed link rate.
1917 */
1918 switch (phy_info->programmed_link_rate &
1919 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1920 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 1921 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1922 break;
1923 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1924 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1925 break;
1926 default:
1927 break;
1928 }
1929
1930 /*
1931 * Set Min hardware link rate.
1932 */
1933 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1934 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 1935 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1936 break;
1937 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1938 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1939 break;
1940 default:
1941 break;
1942 }
1943
1944 /*
1945 * Set Min programmed link rate.
1946 */
1947 switch (phy_info->programmed_link_rate &
1948 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1949 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 1950 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1951 break;
1952 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1953 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1954 break;
1955 default:
1956 break;
1957 }
1958
e6b2d76a 1959 if (!phy_info->phy) {
ac01bbbd 1960
e6b2d76a
ME
1961 error = sas_phy_add(phy);
1962 if (error) {
1963 sas_phy_free(phy);
547f9a21 1964 goto out;
e6b2d76a
ME
1965 }
1966 phy_info->phy = phy;
0c33b27d
CH
1967 }
1968
547f9a21
EM
1969 if (!phy_info->attached.handle ||
1970 !phy_info->port_details)
1971 goto out;
1972
1973 port = mptsas_get_port(phy_info);
1974 ioc = phy_to_ioc(phy_info->phy);
1975
1976 if (phy_info->sas_port_add_phy) {
1977
1978 if (!port) {
dc22f16d 1979 port = sas_port_alloc_num(dev);
547f9a21
EM
1980 if (!port) {
1981 error = -ENOMEM;
1982 goto out;
1983 }
1984 error = sas_port_add(port);
1985 if (error) {
d6ecdd63 1986 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
1987 "%s: exit at line=%d\n", ioc->name,
1988 __FUNCTION__, __LINE__));
1989 goto out;
1990 }
d6ecdd63 1991 mptsas_set_port(ioc, phy_info, port);
29dd3609 1992 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
dc22f16d 1993 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
29dd3609 1994 ioc->name, port, dev, port->port_identifier));
547f9a21 1995 }
29dd3609
EM
1996 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
1997 ioc->name, phy_info->phy_id));
547f9a21
EM
1998 sas_port_add_phy(port, phy_info->phy);
1999 phy_info->sas_port_add_phy = 0;
2000 }
2001
2002 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 2003
0c33b27d 2004 struct sas_rphy *rphy;
2686de27 2005 struct device *parent;
f013db32 2006 struct sas_identify identify;
0c33b27d 2007
2686de27 2008 parent = dev->parent->parent;
e6b2d76a
ME
2009 /*
2010 * Let the hotplug_work thread handle processing
2011 * the adding/removing of devices that occur
2012 * after start of day.
2013 */
2014 if (ioc->sas_discovery_runtime &&
2015 mptsas_is_end_device(&phy_info->attached))
547f9a21 2016 goto out;
e6b2d76a 2017
f013db32 2018 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
2019 if (scsi_is_host_device(parent)) {
2020 struct mptsas_portinfo *port_info;
2021 int i;
2022
2023 mutex_lock(&ioc->sas_topology_mutex);
2024 port_info = mptsas_find_portinfo_by_handle(ioc,
2025 ioc->handle);
2026 mutex_unlock(&ioc->sas_topology_mutex);
2027
2028 for (i = 0; i < port_info->num_phys; i++)
2029 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
2030 identify.sas_address) {
2031 sas_port_mark_backlink(port);
2686de27 2032 goto out;
0c269e6d 2033 }
2686de27
JB
2034
2035 } else if (scsi_is_sas_rphy(parent)) {
2036 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2037 if (identify.sas_address ==
0c269e6d
JB
2038 parent_rphy->identify.sas_address) {
2039 sas_port_mark_backlink(port);
2686de27 2040 goto out;
0c269e6d 2041 }
2686de27
JB
2042 }
2043
f013db32
JB
2044 switch (identify.device_type) {
2045 case SAS_END_DEVICE:
547f9a21 2046 rphy = sas_end_device_alloc(port);
f013db32
JB
2047 break;
2048 case SAS_EDGE_EXPANDER_DEVICE:
2049 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 2050 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
2051 break;
2052 default:
2053 rphy = NULL;
2054 break;
2055 }
547f9a21 2056 if (!rphy) {
d6ecdd63 2057 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2058 "%s: exit at line=%d\n", ioc->name,
2059 __FUNCTION__, __LINE__));
2060 goto out;
2061 }
0c33b27d 2062
f013db32 2063 rphy->identify = identify;
0c33b27d
CH
2064 error = sas_rphy_add(rphy);
2065 if (error) {
d6ecdd63 2066 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2067 "%s: exit at line=%d\n", ioc->name,
2068 __FUNCTION__, __LINE__));
0c33b27d 2069 sas_rphy_free(rphy);
547f9a21 2070 goto out;
0c33b27d 2071 }
d6ecdd63 2072 mptsas_set_rphy(ioc, phy_info, rphy);
0c33b27d
CH
2073 }
2074
547f9a21
EM
2075 out:
2076 return error;
0c33b27d
CH
2077}
2078
2079static int
e6b2d76a 2080mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 2081{
e6b2d76a 2082 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
2083 int error = -ENOMEM, i;
2084
e6b2d76a
ME
2085 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
2086 if (! hba)
0c33b27d 2087 goto out;
0c33b27d 2088
e6b2d76a 2089 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
2090 if (error)
2091 goto out_free_port_info;
2092
edb9068d 2093 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 2094 mutex_lock(&ioc->sas_topology_mutex);
2ecce492
EM
2095 ioc->handle = hba->phy_info[0].handle;
2096 port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
e6b2d76a
ME
2097 if (!port_info) {
2098 port_info = hba;
2099 list_add_tail(&port_info->list, &ioc->sas_topology);
2100 } else {
2ecce492 2101 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
2102 port_info->phy_info[i].negotiated_link_rate =
2103 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
2104 port_info->phy_info[i].handle =
2105 hba->phy_info[i].handle;
2106 port_info->phy_info[i].port_id =
2107 hba->phy_info[i].port_id;
2108 }
547f9a21 2109 kfree(hba->phy_info);
e6b2d76a
ME
2110 kfree(hba);
2111 hba = NULL;
2112 }
9a28f49a 2113 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
2114 for (i = 0; i < port_info->num_phys; i++) {
2115 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2116 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2117 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2118
2119 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
2120 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2121 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2122 port_info->phy_info[i].handle);
024358ee 2123 port_info->phy_info[i].identify.phy_id =
2ecce492 2124 port_info->phy_info[i].phy_id = i;
547f9a21 2125 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
2126 mptsas_sas_device_pg0(ioc,
2127 &port_info->phy_info[i].attached,
2128 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2129 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2130 port_info->phy_info[i].attached.handle);
547f9a21 2131 }
0c33b27d 2132
547f9a21
EM
2133 mptsas_setup_wide_ports(ioc, port_info);
2134
2135 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 2136 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 2137 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
2138
2139 return 0;
2140
2141 out_free_port_info:
547f9a21 2142 kfree(hba);
0c33b27d
CH
2143 out:
2144 return error;
2145}
2146
2147static int
e6b2d76a 2148mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
0c33b27d 2149{
e6b2d76a 2150 struct mptsas_portinfo *port_info, *p, *ex;
547f9a21
EM
2151 struct device *parent;
2152 struct sas_rphy *rphy;
0c33b27d
CH
2153 int error = -ENOMEM, i, j;
2154
e6b2d76a
ME
2155 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2156 if (!ex)
0c33b27d 2157 goto out;
0c33b27d 2158
e6b2d76a 2159 error = mptsas_sas_expander_pg0(ioc, ex,
2ecce492
EM
2160 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2161 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
0c33b27d
CH
2162 if (error)
2163 goto out_free_port_info;
2164
2ecce492 2165 *handle = ex->phy_info[0].handle;
0c33b27d 2166
9a28f49a 2167 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
2168 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2169 if (!port_info) {
2170 port_info = ex;
2171 list_add_tail(&port_info->list, &ioc->sas_topology);
2172 } else {
2ecce492
EM
2173 for (i = 0; i < ex->num_phys; i++) {
2174 port_info->phy_info[i].handle =
2175 ex->phy_info[i].handle;
2176 port_info->phy_info[i].port_id =
2177 ex->phy_info[i].port_id;
2178 }
547f9a21 2179 kfree(ex->phy_info);
e6b2d76a
ME
2180 kfree(ex);
2181 ex = NULL;
2182 }
9a28f49a
CH
2183 mutex_unlock(&ioc->sas_topology_mutex);
2184
0c33b27d 2185 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d
CH
2186 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2187 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2188 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2189
2190 if (port_info->phy_info[i].identify.handle) {
2191 mptsas_sas_device_pg0(ioc,
2192 &port_info->phy_info[i].identify,
2193 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2194 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2195 port_info->phy_info[i].identify.handle);
024358ee
EM
2196 port_info->phy_info[i].identify.phy_id =
2197 port_info->phy_info[i].phy_id;
0c33b27d
CH
2198 }
2199
2200 if (port_info->phy_info[i].attached.handle) {
2201 mptsas_sas_device_pg0(ioc,
2202 &port_info->phy_info[i].attached,
2203 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2204 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2205 port_info->phy_info[i].attached.handle);
db9c9174
ME
2206 port_info->phy_info[i].attached.phy_id =
2207 port_info->phy_info[i].phy_id;
0c33b27d 2208 }
547f9a21 2209 }
0c33b27d 2210
547f9a21
EM
2211 parent = &ioc->sh->shost_gendev;
2212 for (i = 0; i < port_info->num_phys; i++) {
9a28f49a 2213 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
2214 list_for_each_entry(p, &ioc->sas_topology, list) {
2215 for (j = 0; j < p->num_phys; j++) {
547f9a21 2216 if (port_info->phy_info[i].identify.handle !=
0c33b27d 2217 p->phy_info[j].attached.handle)
547f9a21
EM
2218 continue;
2219 rphy = mptsas_get_rphy(&p->phy_info[j]);
2220 parent = &rphy->dev;
0c33b27d
CH
2221 }
2222 }
9a28f49a 2223 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
2224 }
2225
2226 mptsas_setup_wide_ports(ioc, port_info);
0c33b27d 2227
547f9a21 2228 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
ac01bbbd 2229 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
e6b2d76a 2230 ioc->sas_index, 0);
0c33b27d
CH
2231
2232 return 0;
2233
2234 out_free_port_info:
e6b2d76a 2235 if (ex) {
547f9a21 2236 kfree(ex->phy_info);
e6b2d76a
ME
2237 kfree(ex);
2238 }
0c33b27d
CH
2239 out:
2240 return error;
2241}
2242
e6b2d76a
ME
2243/*
2244 * mptsas_delete_expander_phys
2245 *
2246 *
2247 * This will traverse topology, and remove expanders
2248 * that are no longer present
2249 */
2250static void
2251mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2252{
2253 struct mptsas_portinfo buffer;
2254 struct mptsas_portinfo *port_info, *n, *parent;
547f9a21 2255 struct mptsas_phyinfo *phy_info;
547f9a21 2256 struct sas_port * port;
e6b2d76a 2257 int i;
547f9a21 2258 u64 expander_sas_address;
e6b2d76a
ME
2259
2260 mutex_lock(&ioc->sas_topology_mutex);
2261 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2262
2263 if (port_info->phy_info &&
2264 (!(port_info->phy_info[0].identify.device_info &
2265 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
2266 continue;
2267
2268 if (mptsas_sas_expander_pg0(ioc, &buffer,
2269 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2ecce492
EM
2270 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2271 port_info->phy_info[0].handle)) {
e6b2d76a
ME
2272
2273 /*
2274 * Obtain the port_info instance to the parent port
2275 */
2276 parent = mptsas_find_portinfo_by_handle(ioc,
2277 port_info->phy_info[0].identify.handle_parent);
2278
2279 if (!parent)
2280 goto next_port;
2281
547f9a21
EM
2282 expander_sas_address =
2283 port_info->phy_info[0].identify.sas_address;
2284
e6b2d76a
ME
2285 /*
2286 * Delete rphys in the parent that point
2287 * to this expander. The transport layer will
2288 * cleanup all the children.
2289 */
547f9a21
EM
2290 phy_info = parent->phy_info;
2291 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2292 port = mptsas_get_port(phy_info);
2293 if (!port)
2294 continue;
2295 if (phy_info->attached.sas_address !=
2296 expander_sas_address)
e6b2d76a 2297 continue;
d6ecdd63 2298 dsaswideprintk(ioc,
29dd3609
EM
2299 dev_printk(MYIOC_s_DEBUG_FMT, &port->dev,
2300 "delete port (%d)\n", ioc->name, port->port_identifier));
547f9a21 2301 sas_port_delete(port);
d6ecdd63 2302 mptsas_port_delete(ioc, phy_info->port_details);
e6b2d76a
ME
2303 }
2304 next_port:
547f9a21
EM
2305
2306 phy_info = port_info->phy_info;
2307 for (i = 0; i < port_info->num_phys; i++, phy_info++)
d6ecdd63 2308 mptsas_port_delete(ioc, phy_info->port_details);
547f9a21 2309
e6b2d76a 2310 list_del(&port_info->list);
547f9a21 2311 kfree(port_info->phy_info);
e6b2d76a
ME
2312 kfree(port_info);
2313 }
2314 /*
2315 * Free this memory allocated from inside
2316 * mptsas_sas_expander_pg0
2317 */
547f9a21 2318 kfree(buffer.phy_info);
e6b2d76a
ME
2319 }
2320 mutex_unlock(&ioc->sas_topology_mutex);
2321}
2322
2323/*
2324 * Start of day discovery
2325 */
0c33b27d
CH
2326static void
2327mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2328{
2329 u32 handle = 0xFFFF;
f44e5461 2330 int i;
0c33b27d 2331
e6b2d76a
ME
2332 mutex_lock(&ioc->sas_discovery_mutex);
2333 mptsas_probe_hba_phys(ioc);
2334 while (!mptsas_probe_expander_phys(ioc, &handle))
0c33b27d 2335 ;
f44e5461
ME
2336 /*
2337 Reporting RAID volumes.
2338 */
b506ade9
EM
2339 if (!ioc->ir_firmware)
2340 goto out;
f44e5461
ME
2341 if (!ioc->raid_data.pIocPg2)
2342 goto out;
2343 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2344 goto out;
793955f5 2345 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
e8bf3941 2346 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
f44e5461
ME
2347 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2348 }
2349 out:
e6b2d76a
ME
2350 mutex_unlock(&ioc->sas_discovery_mutex);
2351}
2352
2353/*
2354 * Work queue thread to handle Runtime discovery
2355 * Mere purpose is the hot add/delete of expanders
547f9a21 2356 *(Mutex UNLOCKED)
e6b2d76a
ME
2357 */
2358static void
547f9a21 2359__mptsas_discovery_work(MPT_ADAPTER *ioc)
e6b2d76a 2360{
e6b2d76a
ME
2361 u32 handle = 0xFFFF;
2362
e6b2d76a
ME
2363 ioc->sas_discovery_runtime=1;
2364 mptsas_delete_expander_phys(ioc);
2365 mptsas_probe_hba_phys(ioc);
2366 while (!mptsas_probe_expander_phys(ioc, &handle))
2367 ;
e6b2d76a 2368 ioc->sas_discovery_runtime=0;
547f9a21
EM
2369}
2370
2371/*
2372 * Work queue thread to handle Runtime discovery
2373 * Mere purpose is the hot add/delete of expanders
2374 *(Mutex LOCKED)
2375 */
2376static void
c4028958 2377mptsas_discovery_work(struct work_struct *work)
547f9a21 2378{
c4028958
DH
2379 struct mptsas_discovery_event *ev =
2380 container_of(work, struct mptsas_discovery_event, work);
547f9a21
EM
2381 MPT_ADAPTER *ioc = ev->ioc;
2382
2383 mutex_lock(&ioc->sas_discovery_mutex);
2384 __mptsas_discovery_work(ioc);
e6b2d76a 2385 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2386 kfree(ev);
0c33b27d
CH
2387}
2388
9a28f49a 2389static struct mptsas_phyinfo *
547f9a21 2390mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
2391{
2392 struct mptsas_portinfo *port_info;
9a28f49a 2393 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 2394 int i;
9a28f49a 2395
9a28f49a
CH
2396 mutex_lock(&ioc->sas_topology_mutex);
2397 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2398 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
2399 if (!mptsas_is_end_device(
2400 &port_info->phy_info[i].attached))
2401 continue;
547f9a21
EM
2402 if (port_info->phy_info[i].attached.sas_address
2403 != sas_address)
2404 continue;
b506ade9
EM
2405 phy_info = &port_info->phy_info[i];
2406 break;
2407 }
2408 }
2409 mutex_unlock(&ioc->sas_topology_mutex);
2410 return phy_info;
2411}
2412
2413static struct mptsas_phyinfo *
2414mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
2415{
2416 struct mptsas_portinfo *port_info;
2417 struct mptsas_phyinfo *phy_info = NULL;
2418 int i;
2419
2420 mutex_lock(&ioc->sas_topology_mutex);
2421 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2422 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2423 if (!mptsas_is_end_device(
2424 &port_info->phy_info[i].attached))
2425 continue;
b506ade9
EM
2426 if (port_info->phy_info[i].attached.id != id)
2427 continue;
2428 if (port_info->phy_info[i].attached.channel != channel)
2429 continue;
547f9a21
EM
2430 phy_info = &port_info->phy_info[i];
2431 break;
9a28f49a
CH
2432 }
2433 }
2434 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2435 return phy_info;
2436}
2437
2438static struct mptsas_phyinfo *
b506ade9 2439mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
9a28f49a
CH
2440{
2441 struct mptsas_portinfo *port_info;
2442 struct mptsas_phyinfo *phy_info = NULL;
2443 int i;
2444
9a28f49a
CH
2445 mutex_lock(&ioc->sas_topology_mutex);
2446 list_for_each_entry(port_info, &ioc->sas_topology, list) {
547f9a21 2447 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2448 if (!mptsas_is_end_device(
2449 &port_info->phy_info[i].attached))
2450 continue;
b506ade9
EM
2451 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2452 continue;
2453 if (port_info->phy_info[i].attached.phys_disk_num != id)
2454 continue;
2455 if (port_info->phy_info[i].attached.channel != channel)
2456 continue;
547f9a21
EM
2457 phy_info = &port_info->phy_info[i];
2458 break;
2459 }
9a28f49a
CH
2460 }
2461 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2462 return phy_info;
2463}
2464
4b766471
ME
2465/*
2466 * Work queue thread to clear the persitency table
2467 */
2468static void
c4028958 2469mptsas_persist_clear_table(struct work_struct *work)
4b766471 2470{
c4028958 2471 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
4b766471
ME
2472
2473 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2474}
2475
f44e5461
ME
2476static void
2477mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2478{
f99be43b
EM
2479 int rc;
2480
f44e5461 2481 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 2482 rc = scsi_device_reprobe(sdev);
f44e5461
ME
2483}
2484
2485static void
2486mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2487{
2488 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2489 mptsas_reprobe_lun);
2490}
2491
b506ade9
EM
2492static void
2493mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2494{
2495 CONFIGPARMS cfg;
2496 ConfigPageHeader_t hdr;
2497 dma_addr_t dma_handle;
2498 pRaidVolumePage0_t buffer = NULL;
2499 RaidPhysDiskPage0_t phys_disk;
2500 int i;
2501 struct mptsas_hotplug_event *ev;
2502
2503 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2504 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2505 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2506 cfg.pageAddr = (channel << 8) + id;
2507 cfg.cfghdr.hdr = &hdr;
2508 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2509
2510 if (mpt_config(ioc, &cfg) != 0)
2511 goto out;
2512
2513 if (!hdr.PageLength)
2514 goto out;
2515
2516 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2517 &dma_handle);
2518
2519 if (!buffer)
2520 goto out;
2521
2522 cfg.physAddr = dma_handle;
2523 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2524
2525 if (mpt_config(ioc, &cfg) != 0)
2526 goto out;
2527
2528 if (!(buffer->VolumeStatus.Flags &
2529 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2530 goto out;
2531
2532 if (!buffer->NumPhysDisks)
2533 goto out;
2534
2535 for (i = 0; i < buffer->NumPhysDisks; i++) {
2536
2537 if (mpt_raid_phys_disk_pg0(ioc,
2538 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2539 continue;
2540
2541 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2542 if (!ev) {
29dd3609 2543 printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
b506ade9
EM
2544 goto out;
2545 }
2546
2547 INIT_WORK(&ev->work, mptsas_hotplug_work);
2548 ev->ioc = ioc;
2549 ev->id = phys_disk.PhysDiskID;
2550 ev->channel = phys_disk.PhysDiskBus;
2551 ev->phys_disk_num_valid = 1;
2552 ev->phys_disk_num = phys_disk.PhysDiskNum;
2553 ev->event_type = MPTSAS_ADD_DEVICE;
2554 schedule_work(&ev->work);
2555 }
2556
2557 out:
2558 if (buffer)
2559 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2560 dma_handle);
2561}
e6b2d76a
ME
2562/*
2563 * Work queue thread to handle SAS hotplug events
2564 */
9a28f49a 2565static void
c4028958 2566mptsas_hotplug_work(struct work_struct *work)
9a28f49a 2567{
c4028958
DH
2568 struct mptsas_hotplug_event *ev =
2569 container_of(work, struct mptsas_hotplug_event, work);
b506ade9 2570
9a28f49a
CH
2571 MPT_ADAPTER *ioc = ev->ioc;
2572 struct mptsas_phyinfo *phy_info;
2573 struct sas_rphy *rphy;
547f9a21 2574 struct sas_port *port;
c73787ee 2575 struct scsi_device *sdev;
547f9a21 2576 struct scsi_target * starget;
f013db32 2577 struct sas_identify identify;
9a28f49a 2578 char *ds = NULL;
c73787ee 2579 struct mptsas_devinfo sas_device;
f44e5461 2580 VirtTarget *vtarget;
547f9a21 2581 VirtDevice *vdevice;
9a28f49a 2582
547f9a21 2583 mutex_lock(&ioc->sas_discovery_mutex);
9a28f49a
CH
2584 switch (ev->event_type) {
2585 case MPTSAS_DEL_DEVICE:
9a28f49a 2586
b506ade9
EM
2587 phy_info = NULL;
2588 if (ev->phys_disk_num_valid) {
2589 if (ev->hidden_raid_component){
2590 if (mptsas_sas_device_pg0(ioc, &sas_device,
2591 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2592 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2593 (ev->channel << 8) + ev->id)) {
d6ecdd63 2594 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
b506ade9
EM
2595 "%s: exit at line=%d\n", ioc->name,
2596 __FUNCTION__, __LINE__));
2597 break;
2598 }
2599 phy_info = mptsas_find_phyinfo_by_sas_address(
2600 ioc, sas_device.sas_address);
2601 }else
2602 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2603 ioc, ev->channel, ev->phys_disk_num);
2604 }
2605
2606 if (!phy_info)
2607 phy_info = mptsas_find_phyinfo_by_target(ioc,
2608 ev->channel, ev->id);
e6b2d76a 2609
f44e5461
ME
2610 /*
2611 * Sanity checks, for non-existing phys and remote rphys.
2612 */
b506ade9 2613 if (!phy_info){
d6ecdd63 2614 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
b506ade9
EM
2615 "%s: exit at line=%d\n", ioc->name,
2616 __FUNCTION__, __LINE__));
2617 break;
2618 }
2619 if (!phy_info->port_details) {
d6ecdd63 2620 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2621 "%s: exit at line=%d\n", ioc->name,
2622 __FUNCTION__, __LINE__));
9a28f49a 2623 break;
547f9a21
EM
2624 }
2625 rphy = mptsas_get_rphy(phy_info);
2626 if (!rphy) {
d6ecdd63 2627 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2628 "%s: exit at line=%d\n", ioc->name,
2629 __FUNCTION__, __LINE__));
2630 break;
2631 }
b506ade9 2632
547f9a21
EM
2633 port = mptsas_get_port(phy_info);
2634 if (!port) {
d6ecdd63 2635 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2636 "%s: exit at line=%d\n", ioc->name,
2637 __FUNCTION__, __LINE__));
f44e5461 2638 break;
547f9a21
EM
2639 }
2640
2641 starget = mptsas_get_starget(phy_info);
2642 if (starget) {
2643 vtarget = starget->hostdata;
f44e5461 2644
547f9a21 2645 if (!vtarget) {
d6ecdd63 2646 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2647 "%s: exit at line=%d\n", ioc->name,
2648 __FUNCTION__, __LINE__));
f44e5461 2649 break;
547f9a21
EM
2650 }
2651
f44e5461
ME
2652 /*
2653 * Handling RAID components
2654 */
b506ade9
EM
2655 if (ev->phys_disk_num_valid &&
2656 ev->hidden_raid_component) {
2657 printk(MYIOC_s_INFO_FMT
2658 "RAID Hidding: channel=%d, id=%d, "
2659 "physdsk %d \n", ioc->name, ev->channel,
2660 ev->id, ev->phys_disk_num);
793955f5 2661 vtarget->id = ev->phys_disk_num;
b506ade9
EM
2662 vtarget->tflags |=
2663 MPT_TARGET_FLAGS_RAID_COMPONENT;
547f9a21 2664 mptsas_reprobe_target(starget, 1);
b506ade9
EM
2665 phy_info->attached.phys_disk_num =
2666 ev->phys_disk_num;
2667 break;
f44e5461 2668 }
9a28f49a
CH
2669 }
2670
b506ade9
EM
2671 if (phy_info->attached.device_info &
2672 MPI_SAS_DEVICE_INFO_SSP_TARGET)
c73787ee 2673 ds = "ssp";
b506ade9
EM
2674 if (phy_info->attached.device_info &
2675 MPI_SAS_DEVICE_INFO_STP_TARGET)
c73787ee 2676 ds = "stp";
b506ade9
EM
2677 if (phy_info->attached.device_info &
2678 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
c73787ee
ME
2679 ds = "sata";
2680
2681 printk(MYIOC_s_INFO_FMT
2682 "removing %s device, channel %d, id %d, phy %d\n",
2683 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
29dd3609
EM
2684 dev_printk(MYIOC_s_DEBUG_FMT, &port->dev,
2685 "delete port (%d)\n", ioc->name, port->port_identifier);
547f9a21 2686 sas_port_delete(port);
d6ecdd63 2687 mptsas_port_delete(ioc, phy_info->port_details);
9a28f49a
CH
2688 break;
2689 case MPTSAS_ADD_DEVICE:
c73787ee 2690
bd23e94c
ME
2691 if (ev->phys_disk_num_valid)
2692 mpt_findImVolumes(ioc);
2693
c73787ee 2694 /*
e3094447 2695 * Refresh sas device pg0 data
c73787ee 2696 */
e3094447
CH
2697 if (mptsas_sas_device_pg0(ioc, &sas_device,
2698 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9
EM
2699 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2700 (ev->channel << 8) + ev->id)) {
d6ecdd63 2701 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2702 "%s: exit at line=%d\n", ioc->name,
2703 __FUNCTION__, __LINE__));
e3094447 2704 break;
547f9a21 2705 }
9a28f49a 2706
547f9a21 2707 __mptsas_discovery_work(ioc);
e6b2d76a 2708
547f9a21
EM
2709 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2710 sas_device.sas_address);
e6b2d76a 2711
547f9a21 2712 if (!phy_info || !phy_info->port_details) {
d6ecdd63 2713 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2714 "%s: exit at line=%d\n", ioc->name,
2715 __FUNCTION__, __LINE__));
2716 break;
e6b2d76a
ME
2717 }
2718
547f9a21 2719 starget = mptsas_get_starget(phy_info);
b506ade9
EM
2720 if (starget && (!ev->hidden_raid_component)){
2721
547f9a21 2722 vtarget = starget->hostdata;
9a28f49a 2723
547f9a21 2724 if (!vtarget) {
d6ecdd63 2725 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
29dd3609
EM
2726 "%s: exit at line=%d\n", ioc->name,
2727 __FUNCTION__, __LINE__));
f44e5461 2728 break;
547f9a21 2729 }
f44e5461
ME
2730 /*
2731 * Handling RAID components
2732 */
2733 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
b506ade9
EM
2734 printk(MYIOC_s_INFO_FMT
2735 "RAID Exposing: channel=%d, id=%d, "
2736 "physdsk %d \n", ioc->name, ev->channel,
2737 ev->id, ev->phys_disk_num);
2738 vtarget->tflags &=
2739 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
793955f5 2740 vtarget->id = ev->id;
547f9a21 2741 mptsas_reprobe_target(starget, 0);
b506ade9 2742 phy_info->attached.phys_disk_num = ~0;
f44e5461 2743 }
9a28f49a
CH
2744 break;
2745 }
2746
547f9a21 2747 if (mptsas_get_rphy(phy_info)) {
d6ecdd63 2748 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2749 "%s: exit at line=%d\n", ioc->name,
2750 __FUNCTION__, __LINE__));
b506ade9 2751 if (ev->channel) printk("%d\n", __LINE__);
f44e5461 2752 break;
547f9a21 2753 }
b506ade9 2754
547f9a21
EM
2755 port = mptsas_get_port(phy_info);
2756 if (!port) {
d6ecdd63 2757 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2758 "%s: exit at line=%d\n", ioc->name,
2759 __FUNCTION__, __LINE__));
2760 break;
2761 }
e3094447
CH
2762 memcpy(&phy_info->attached, &sas_device,
2763 sizeof(struct mptsas_devinfo));
9a28f49a 2764
b506ade9
EM
2765 if (phy_info->attached.device_info &
2766 MPI_SAS_DEVICE_INFO_SSP_TARGET)
c73787ee 2767 ds = "ssp";
b506ade9
EM
2768 if (phy_info->attached.device_info &
2769 MPI_SAS_DEVICE_INFO_STP_TARGET)
c73787ee 2770 ds = "stp";
b506ade9
EM
2771 if (phy_info->attached.device_info &
2772 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
c73787ee
ME
2773 ds = "sata";
2774
2775 printk(MYIOC_s_INFO_FMT
2776 "attaching %s device, channel %d, id %d, phy %d\n",
2777 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2778
f013db32 2779 mptsas_parse_device_info(&identify, &phy_info->attached);
547f9a21
EM
2780 rphy = sas_end_device_alloc(port);
2781 if (!rphy) {
d6ecdd63 2782 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2783 "%s: exit at line=%d\n", ioc->name,
2784 __FUNCTION__, __LINE__));
9a28f49a 2785 break; /* non-fatal: an rphy can be added later */
547f9a21 2786 }
9a28f49a 2787
f013db32 2788 rphy->identify = identify;
9a28f49a 2789 if (sas_rphy_add(rphy)) {
d6ecdd63 2790 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2791 "%s: exit at line=%d\n", ioc->name,
2792 __FUNCTION__, __LINE__));
9a28f49a
CH
2793 sas_rphy_free(rphy);
2794 break;
2795 }
d6ecdd63 2796 mptsas_set_rphy(ioc, phy_info, rphy);
9a28f49a 2797 break;
c73787ee 2798 case MPTSAS_ADD_RAID:
e8bf3941
JB
2799 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2800 ev->id, 0);
c73787ee
ME
2801 if (sdev) {
2802 scsi_device_put(sdev);
2803 break;
2804 }
2805 printk(MYIOC_s_INFO_FMT
4b766471 2806 "attaching raid volume, channel %d, id %d\n",
e8bf3941
JB
2807 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2808 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
c73787ee
ME
2809 mpt_findImVolumes(ioc);
2810 break;
2811 case MPTSAS_DEL_RAID:
e8bf3941 2812 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
b506ade9 2813 ev->id, 0);
c73787ee
ME
2814 if (!sdev)
2815 break;
2816 printk(MYIOC_s_INFO_FMT
4b766471 2817 "removing raid volume, channel %d, id %d\n",
e8bf3941 2818 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
b506ade9 2819 vdevice = sdev->hostdata;
c73787ee
ME
2820 scsi_remove_device(sdev);
2821 scsi_device_put(sdev);
2822 mpt_findImVolumes(ioc);
2823 break;
b506ade9
EM
2824 case MPTSAS_ADD_INACTIVE_VOLUME:
2825 mptsas_adding_inactive_raid_components(ioc,
2826 ev->channel, ev->id);
2827 break;
bd23e94c
ME
2828 case MPTSAS_IGNORE_EVENT:
2829 default:
2830 break;
9a28f49a
CH
2831 }
2832
e6b2d76a 2833 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2834 kfree(ev);
9a28f49a
CH
2835}
2836
2837static void
547f9a21 2838mptsas_send_sas_event(MPT_ADAPTER *ioc,
9a28f49a
CH
2839 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2840{
2841 struct mptsas_hotplug_event *ev;
2842 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2843 __le64 sas_address;
2844
2845 if ((device_info &
2846 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2847 MPI_SAS_DEVICE_INFO_STP_TARGET |
2848 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2849 return;
2850
4b766471 2851 switch (sas_event_data->ReasonCode) {
4b766471 2852 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a
EM
2853
2854 mptsas_target_reset_queue(ioc, sas_event_data);
2855 break;
2856
2857 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
547f9a21 2858 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
4b766471 2859 if (!ev) {
29dd3609 2860 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
4b766471
ME
2861 break;
2862 }
9a28f49a 2863
c4028958 2864 INIT_WORK(&ev->work, mptsas_hotplug_work);
4b766471
ME
2865 ev->ioc = ioc;
2866 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2867 ev->parent_handle =
2868 le16_to_cpu(sas_event_data->ParentDevHandle);
2869 ev->channel = sas_event_data->Bus;
2870 ev->id = sas_event_data->TargetID;
2871 ev->phy_id = sas_event_data->PhyNum;
2872 memcpy(&sas_address, &sas_event_data->SASAddress,
2873 sizeof(__le64));
2874 ev->sas_address = le64_to_cpu(sas_address);
2875 ev->device_info = device_info;
2876
2877 if (sas_event_data->ReasonCode &
2878 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2879 ev->event_type = MPTSAS_ADD_DEVICE;
2880 else
2881 ev->event_type = MPTSAS_DEL_DEVICE;
2882 schedule_work(&ev->work);
2883 break;
2884 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2885 /*
2886 * Persistent table is full.
2887 */
547f9a21 2888 INIT_WORK(&ioc->sas_persist_task,
c4028958 2889 mptsas_persist_clear_table);
547f9a21 2890 schedule_work(&ioc->sas_persist_task);
4b766471 2891 break;
b506ade9
EM
2892 /*
2893 * TODO, handle other events
2894 */
4b766471 2895 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
b506ade9 2896 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
4b766471 2897 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
b506ade9
EM
2898 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2899 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2900 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2901 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
4b766471
ME
2902 default:
2903 break;
9a28f49a 2904 }
9a28f49a 2905}
c73787ee 2906static void
547f9a21 2907mptsas_send_raid_event(MPT_ADAPTER *ioc,
c73787ee
ME
2908 EVENT_DATA_RAID *raid_event_data)
2909{
2910 struct mptsas_hotplug_event *ev;
bd23e94c
ME
2911 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2912 int state = (status >> 8) & 0xff;
c73787ee
ME
2913
2914 if (ioc->bus_type != SAS)
2915 return;
2916
547f9a21 2917 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
c73787ee 2918 if (!ev) {
29dd3609 2919 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
c73787ee
ME
2920 return;
2921 }
2922
c4028958 2923 INIT_WORK(&ev->work, mptsas_hotplug_work);
c73787ee
ME
2924 ev->ioc = ioc;
2925 ev->id = raid_event_data->VolumeID;
b506ade9 2926 ev->channel = raid_event_data->VolumeBus;
bd23e94c 2927 ev->event_type = MPTSAS_IGNORE_EVENT;
c73787ee
ME
2928
2929 switch (raid_event_data->ReasonCode) {
2930 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
b506ade9
EM
2931 ev->phys_disk_num_valid = 1;
2932 ev->phys_disk_num = raid_event_data->PhysDiskNum;
c73787ee
ME
2933 ev->event_type = MPTSAS_ADD_DEVICE;
2934 break;
2935 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
f44e5461
ME
2936 ev->phys_disk_num_valid = 1;
2937 ev->phys_disk_num = raid_event_data->PhysDiskNum;
b506ade9 2938 ev->hidden_raid_component = 1;
c73787ee
ME
2939 ev->event_type = MPTSAS_DEL_DEVICE;
2940 break;
bd23e94c
ME
2941 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2942 switch (state) {
2943 case MPI_PD_STATE_ONLINE:
b506ade9 2944 case MPI_PD_STATE_NOT_COMPATIBLE:
bd23e94c
ME
2945 ev->phys_disk_num_valid = 1;
2946 ev->phys_disk_num = raid_event_data->PhysDiskNum;
b506ade9 2947 ev->hidden_raid_component = 1;
bd23e94c
ME
2948 ev->event_type = MPTSAS_ADD_DEVICE;
2949 break;
2950 case MPI_PD_STATE_MISSING:
bd23e94c
ME
2951 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2952 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2953 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
b506ade9
EM
2954 ev->phys_disk_num_valid = 1;
2955 ev->phys_disk_num = raid_event_data->PhysDiskNum;
bd23e94c
ME
2956 ev->event_type = MPTSAS_DEL_DEVICE;
2957 break;
2958 default:
2959 break;
2960 }
2961 break;
c73787ee
ME
2962 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2963 ev->event_type = MPTSAS_DEL_RAID;
2964 break;
2965 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2966 ev->event_type = MPTSAS_ADD_RAID;
2967 break;
2968 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
bd23e94c
ME
2969 switch (state) {
2970 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2971 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2972 ev->event_type = MPTSAS_DEL_RAID;
2973 break;
2974 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2975 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2976 ev->event_type = MPTSAS_ADD_RAID;
2977 break;
2978 default:
2979 break;
2980 }
c73787ee
ME
2981 break;
2982 default:
2983 break;
2984 }
2985 schedule_work(&ev->work);
2986}
2987
e6b2d76a 2988static void
547f9a21 2989mptsas_send_discovery_event(MPT_ADAPTER *ioc,
e6b2d76a
ME
2990 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2991{
2992 struct mptsas_discovery_event *ev;
2993
2994 /*
2995 * DiscoveryStatus
2996 *
2997 * This flag will be non-zero when firmware
2998 * kicks off discovery, and return to zero
2999 * once its completed.
3000 */
3001 if (discovery_data->DiscoveryStatus)
3002 return;
3003
547f9a21 3004 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
e6b2d76a
ME
3005 if (!ev)
3006 return;
c4028958 3007 INIT_WORK(&ev->work, mptsas_discovery_work);
e6b2d76a
ME
3008 ev->ioc = ioc;
3009 schedule_work(&ev->work);
3010};
3011
b506ade9
EM
3012/*
3013 * mptsas_send_ir2_event - handle exposing hidden disk when
3014 * an inactive raid volume is added
3015 *
3016 * @ioc: Pointer to MPT_ADAPTER structure
3017 * @ir2_data
3018 *
3019 */
3020static void
3021mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
3022{
3023 struct mptsas_hotplug_event *ev;
3024
3025 if (ir2_data->ReasonCode !=
3026 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
3027 return;
3028
3029 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3030 if (!ev)
3031 return;
3032
3033 INIT_WORK(&ev->work, mptsas_hotplug_work);
3034 ev->ioc = ioc;
3035 ev->id = ir2_data->TargetID;
3036 ev->channel = ir2_data->Bus;
3037 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3038
3039 schedule_work(&ev->work);
3040};
e6b2d76a 3041
9a28f49a
CH
3042static int
3043mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3044{
c73787ee 3045 int rc=1;
9a28f49a
CH
3046 u8 event = le32_to_cpu(reply->Event) & 0xFF;
3047
3048 if (!ioc->sh)
c73787ee 3049 goto out;
9a28f49a 3050
e6b2d76a
ME
3051 /*
3052 * sas_discovery_ignore_events
3053 *
3054 * This flag is to prevent anymore processing of
3055 * sas events once mptsas_remove function is called.
3056 */
3057 if (ioc->sas_discovery_ignore_events) {
3058 rc = mptscsih_event_process(ioc, reply);
3059 goto out;
3060 }
3061
9a28f49a
CH
3062 switch (event) {
3063 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
547f9a21 3064 mptsas_send_sas_event(ioc,
9a28f49a 3065 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
c73787ee
ME
3066 break;
3067 case MPI_EVENT_INTEGRATED_RAID:
547f9a21 3068 mptsas_send_raid_event(ioc,
c73787ee
ME
3069 (EVENT_DATA_RAID *)reply->Data);
3070 break;
79de278e 3071 case MPI_EVENT_PERSISTENT_TABLE_FULL:
547f9a21 3072 INIT_WORK(&ioc->sas_persist_task,
c4028958 3073 mptsas_persist_clear_table);
547f9a21 3074 schedule_work(&ioc->sas_persist_task);
79de278e 3075 break;
4b766471 3076 case MPI_EVENT_SAS_DISCOVERY:
547f9a21 3077 mptsas_send_discovery_event(ioc,
e6b2d76a
ME
3078 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3079 break;
b506ade9
EM
3080 case MPI_EVENT_IR2:
3081 mptsas_send_ir2_event(ioc,
3082 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
3083 break;
9a28f49a 3084 default:
c73787ee
ME
3085 rc = mptscsih_event_process(ioc, reply);
3086 break;
9a28f49a 3087 }
c73787ee
ME
3088 out:
3089
3090 return rc;
9a28f49a
CH
3091}
3092
0c33b27d
CH
3093static int
3094mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3095{
3096 struct Scsi_Host *sh;
3097 MPT_SCSI_HOST *hd;
3098 MPT_ADAPTER *ioc;
3099 unsigned long flags;
1ca00bb7 3100 int ii;
0c33b27d
CH
3101 int numSGE = 0;
3102 int scale;
3103 int ioc_cap;
0c33b27d
CH
3104 int error=0;
3105 int r;
3106
3107 r = mpt_attach(pdev,id);
3108 if (r)
3109 return r;
3110
3111 ioc = pci_get_drvdata(pdev);
3112 ioc->DoneCtx = mptsasDoneCtx;
3113 ioc->TaskCtx = mptsasTaskCtx;
3114 ioc->InternalCtx = mptsasInternalCtx;
3115
3116 /* Added sanity check on readiness of the MPT adapter.
3117 */
3118 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3119 printk(MYIOC_s_WARN_FMT
3120 "Skipping because it's not operational!\n",
3121 ioc->name);
7acec1e7
MED
3122 error = -ENODEV;
3123 goto out_mptsas_probe;
0c33b27d
CH
3124 }
3125
3126 if (!ioc->active) {
3127 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3128 ioc->name);
7acec1e7
MED
3129 error = -ENODEV;
3130 goto out_mptsas_probe;
0c33b27d
CH
3131 }
3132
3133 /* Sanity check - ensure at least 1 port is INITIATOR capable
3134 */
3135 ioc_cap = 0;
3136 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3137 if (ioc->pfacts[ii].ProtocolFlags &
3138 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3139 ioc_cap++;
3140 }
3141
3142 if (!ioc_cap) {
3143 printk(MYIOC_s_WARN_FMT
3144 "Skipping ioc=%p because SCSI Initiator mode "
3145 "is NOT enabled!\n", ioc->name, ioc);
466544d8 3146 return 0;
0c33b27d
CH
3147 }
3148
3149 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3150 if (!sh) {
3151 printk(MYIOC_s_WARN_FMT
3152 "Unable to register controller with SCSI subsystem\n",
3153 ioc->name);
7acec1e7
MED
3154 error = -1;
3155 goto out_mptsas_probe;
0c33b27d
CH
3156 }
3157
3158 spin_lock_irqsave(&ioc->FreeQlock, flags);
3159
3160 /* Attach the SCSI Host to the IOC structure
3161 */
3162 ioc->sh = sh;
3163
3164 sh->io_port = 0;
3165 sh->n_io_port = 0;
3166 sh->irq = 0;
3167
3168 /* set 16 byte cdb's */
3169 sh->max_cmd_len = 16;
3170
793955f5
EM
3171 sh->max_id = ioc->pfacts[0].PortSCSIID;
3172 sh->max_lun = max_lun;
0c33b27d
CH
3173
3174 sh->transportt = mptsas_transport_template;
3175
0c33b27d
CH
3176 sh->this_id = ioc->pfacts[0].PortSCSIID;
3177
3178 /* Required entry.
3179 */
3180 sh->unique_id = ioc->id;
3181
3182 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 3183 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 3184 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 3185 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 3186 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
3187
3188 /* Verify that we won't exceed the maximum
3189 * number of chain buffers
3190 * We can optimize: ZZ = req_sz/sizeof(SGE)
3191 * For 32bit SGE's:
3192 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3193 * + (req_sz - 64)/sizeof(SGE)
3194 * A slightly different algorithm is required for
3195 * 64bit SGEs.
3196 */
3197 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3198 if (sizeof(dma_addr_t) == sizeof(u64)) {
3199 numSGE = (scale - 1) *
3200 (ioc->facts.MaxChainDepth-1) + scale +
3201 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
3202 sizeof(u32));
3203 } else {
3204 numSGE = 1 + (scale - 1) *
3205 (ioc->facts.MaxChainDepth-1) + scale +
3206 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
3207 sizeof(u32));
3208 }
3209
3210 if (numSGE < sh->sg_tablesize) {
3211 /* Reset this value */
d6ecdd63 3212 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
3213 "Resetting sg_tablesize to %d from %d\n",
3214 ioc->name, numSGE, sh->sg_tablesize));
3215 sh->sg_tablesize = numSGE;
3216 }
3217
e7eae9f6 3218 hd = shost_priv(sh);
0c33b27d
CH
3219 hd->ioc = ioc;
3220
3221 /* SCSI needs scsi_cmnd lookup table!
3222 * (with size equal to req_depth*PtrSz!)
3223 */
1ca00bb7
CH
3224 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3225 if (!hd->ScsiLookup) {
0c33b27d 3226 error = -ENOMEM;
bc6e089a 3227 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
7acec1e7 3228 goto out_mptsas_probe;
0c33b27d
CH
3229 }
3230
d6ecdd63 3231 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
1ca00bb7 3232 ioc->name, hd->ScsiLookup));
0c33b27d 3233
0c33b27d
CH
3234 /* Clear the TM flags
3235 */
3236 hd->tmPending = 0;
3237 hd->tmState = TM_STATE_NONE;
3238 hd->resetPending = 0;
3239 hd->abortSCpnt = NULL;
3240
3241 /* Clear the pointer used to store
3242 * single-threaded commands, i.e., those
3243 * issued during a bus scan, dv and
3244 * configuration pages.
3245 */
3246 hd->cmdPtr = NULL;
3247
3248 /* Initialize this SCSI Hosts' timers
3249 * To use, set the timer expires field
3250 * and add_timer
3251 */
3252 init_timer(&hd->timer);
3253 hd->timer.data = (unsigned long) hd;
3254 hd->timer.function = mptscsih_timer_expired;
3255
0c33b27d
CH
3256 ioc->sas_data.ptClear = mpt_pt_clear;
3257
df9e062a
EM
3258 init_waitqueue_head(&hd->scandv_waitq);
3259 hd->scandv_wait_done = 0;
3260 hd->last_queue_full = 0;
3261 INIT_LIST_HEAD(&hd->target_reset_list);
3262 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3263
0c33b27d
CH
3264 if (ioc->sas_data.ptClear==1) {
3265 mptbase_sas_persist_operation(
3266 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3267 }
3268
0c33b27d
CH
3269 error = scsi_add_host(sh, &ioc->pcidev->dev);
3270 if (error) {
29dd3609
EM
3271 dprintk(ioc, printk(MYIOC_s_ERR_FMT
3272 "scsi_add_host failed\n", ioc->name));
7acec1e7 3273 goto out_mptsas_probe;
0c33b27d
CH
3274 }
3275
3276 mptsas_scan_sas_topology(ioc);
3277
3278 return 0;
3279
547f9a21 3280 out_mptsas_probe:
0c33b27d
CH
3281
3282 mptscsih_remove(pdev);
3283 return error;
3284}
3285
3286static void __devexit mptsas_remove(struct pci_dev *pdev)
3287{
3288 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3289 struct mptsas_portinfo *p, *n;
547f9a21 3290 int i;
0c33b27d 3291
b506ade9 3292 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
3293 sas_remove_host(ioc->sh);
3294
9a28f49a 3295 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
3296 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3297 list_del(&p->list);
547f9a21 3298 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 3299 mptsas_port_delete(ioc, p->phy_info[i].port_details);
547f9a21 3300 kfree(p->phy_info);
0c33b27d
CH
3301 kfree(p);
3302 }
9a28f49a 3303 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
3304
3305 mptscsih_remove(pdev);
3306}
3307
3308static struct pci_device_id mptsas_pci_table[] = {
87cf8986 3309 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 3310 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3311 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 3312 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3313 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 3314 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3315 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 3316 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3317 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
3318 PCI_ANY_ID, PCI_ANY_ID },
3319 {0} /* Terminating entry */
3320};
3321MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3322
3323
3324static struct pci_driver mptsas_driver = {
3325 .name = "mptsas",
3326 .id_table = mptsas_pci_table,
3327 .probe = mptsas_probe,
3328 .remove = __devexit_p(mptsas_remove),
3329 .shutdown = mptscsih_shutdown,
3330#ifdef CONFIG_PM
3331 .suspend = mptscsih_suspend,
3332 .resume = mptscsih_resume,
3333#endif
3334};
3335
3336static int __init
3337mptsas_init(void)
3338{
57ce21bf
PS
3339 int error;
3340
0c33b27d
CH
3341 show_mptmod_ver(my_NAME, my_VERSION);
3342
3343 mptsas_transport_template =
3344 sas_attach_transport(&mptsas_transport_functions);
3345 if (!mptsas_transport_template)
3346 return -ENODEV;
3347
3348 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
df9e062a 3349 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d
CH
3350 mptsasInternalCtx =
3351 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 3352 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
0c33b27d 3353
d6ecdd63
PS
3354 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3355 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 3356
57ce21bf
PS
3357 error = pci_register_driver(&mptsas_driver);
3358 if (error)
3359 sas_release_transport(mptsas_transport_template);
3360
3361 return error;
0c33b27d
CH
3362}
3363
3364static void __exit
3365mptsas_exit(void)
3366{
3367 pci_unregister_driver(&mptsas_driver);
3368 sas_release_transport(mptsas_transport_template);
3369
3370 mpt_reset_deregister(mptsasDoneCtx);
3371 mpt_event_deregister(mptsasDoneCtx);
3372
da4fa655 3373 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
3374 mpt_deregister(mptsasInternalCtx);
3375 mpt_deregister(mptsasTaskCtx);
3376 mpt_deregister(mptsasDoneCtx);
3377}
3378
3379module_init(mptsas_init);
3380module_exit(mptsas_exit);
This page took 0.372405 seconds and 5 git commands to generate.