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