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