Skip to content

Commit 1dc5ec2

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: add Trunking support
Add trunking support to the driver. Trunking is found on more recent asics. In general, trunking appears as a single "port" to the driver and overall behavior doesn't differ. Link speed is reported as an aggregate value, while link speed control is done on a per-physical link basis with all links in the trunk symmetrical. Some commands returning port information are updated to additionally provide trunking information. And new ACQEs are generated to report physical link events relative to the trunk. This patch contains the following modifications: - Added link speed settings of 128GB and 256GB. - Added handling of trunk-related ACQEs, mainly logging and trapping of physical link statuses. - Added additional bsg interface to query trunk state by applications. - Augment link_state sysfs attribtute to display trunk link status Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 7ea92eb commit 1dc5ec2

File tree

12 files changed

+474
-0
lines changed

12 files changed

+474
-0
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,18 @@ enum hba_state {
335335
LPFC_HBA_ERROR = -1
336336
};
337337

338+
struct lpfc_trunk_link_state {
339+
enum hba_state state;
340+
uint8_t fault;
341+
};
342+
343+
struct lpfc_trunk_link {
344+
struct lpfc_trunk_link_state link0,
345+
link1,
346+
link2,
347+
link3;
348+
};
349+
338350
struct lpfc_vport {
339351
struct lpfc_hba *phba;
340352
struct list_head listentry;
@@ -684,6 +696,7 @@ struct lpfc_hba {
684696
uint32_t iocb_cmd_size;
685697
uint32_t iocb_rsp_size;
686698

699+
struct lpfc_trunk_link trunk_link;
687700
enum hba_state link_state;
688701
uint32_t link_flag; /* link state flags */
689702
#define LS_LOOPBACK_MODE 0x1 /* NPort is in Loopback mode */

drivers/scsi/lpfc/lpfc_attr.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,42 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
883883
}
884884
}
885885

886+
if ((phba->sli_rev == LPFC_SLI_REV4) &&
887+
((bf_get(lpfc_sli_intf_if_type,
888+
&phba->sli4_hba.sli_intf) ==
889+
LPFC_SLI_INTF_IF_TYPE_6))) {
890+
struct lpfc_trunk_link link = phba->trunk_link;
891+
892+
if (bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba))
893+
len += snprintf(buf + len, PAGE_SIZE - len,
894+
"Trunk port 0: Link %s %s\n",
895+
(link.link0.state == LPFC_LINK_UP) ?
896+
"Up" : "Down. ",
897+
trunk_errmsg[link.link0.fault]);
898+
899+
if (bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba))
900+
len += snprintf(buf + len, PAGE_SIZE - len,
901+
"Trunk port 1: Link %s %s\n",
902+
(link.link1.state == LPFC_LINK_UP) ?
903+
"Up" : "Down. ",
904+
trunk_errmsg[link.link1.fault]);
905+
906+
if (bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba))
907+
len += snprintf(buf + len, PAGE_SIZE - len,
908+
"Trunk port 2: Link %s %s\n",
909+
(link.link2.state == LPFC_LINK_UP) ?
910+
"Up" : "Down. ",
911+
trunk_errmsg[link.link2.fault]);
912+
913+
if (bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba))
914+
len += snprintf(buf + len, PAGE_SIZE - len,
915+
"Trunk port 3: Link %s %s\n",
916+
(link.link3.state == LPFC_LINK_UP) ?
917+
"Up" : "Down. ",
918+
trunk_errmsg[link.link3.fault]);
919+
920+
}
921+
886922
return len;
887923
}
888924

@@ -1430,6 +1466,66 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
14301466
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
14311467
}
14321468

1469+
int
1470+
lpfc_set_trunking(struct lpfc_hba *phba, char *buff_out)
1471+
{
1472+
LPFC_MBOXQ_t *mbox = NULL;
1473+
unsigned long val = 0;
1474+
char *pval = 0;
1475+
int rc = 0;
1476+
1477+
if (!strncmp("enable", buff_out,
1478+
strlen("enable"))) {
1479+
pval = buff_out + strlen("enable") + 1;
1480+
rc = kstrtoul(pval, 0, &val);
1481+
if (rc)
1482+
return rc; /* Invalid number */
1483+
} else if (!strncmp("disable", buff_out,
1484+
strlen("disable"))) {
1485+
val = 0;
1486+
} else {
1487+
return -EINVAL; /* Invalid command */
1488+
}
1489+
1490+
switch (val) {
1491+
case 0:
1492+
val = 0x0; /* Disable */
1493+
break;
1494+
case 2:
1495+
val = 0x1; /* Enable two port trunk */
1496+
break;
1497+
case 4:
1498+
val = 0x2; /* Enable four port trunk */
1499+
break;
1500+
default:
1501+
return -EINVAL;
1502+
}
1503+
1504+
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
1505+
"0070 Set trunk mode with val %ld ", val);
1506+
1507+
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1508+
if (!mbox)
1509+
return -ENOMEM;
1510+
1511+
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
1512+
LPFC_MBOX_OPCODE_FCOE_FC_SET_TRUNK_MODE,
1513+
12, LPFC_SLI4_MBX_EMBED);
1514+
1515+
bf_set(lpfc_mbx_set_trunk_mode,
1516+
&mbox->u.mqe.un.set_trunk_mode,
1517+
val);
1518+
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
1519+
if (rc)
1520+
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
1521+
"0071 Set trunk mode failed with status: %d",
1522+
rc);
1523+
if (rc != MBX_TIMEOUT)
1524+
mempool_free(mbox, phba->mbox_mem_pool);
1525+
1526+
return 0;
1527+
}
1528+
14331529
/**
14341530
* lpfc_board_mode_show - Return the state of the board
14351531
* @dev: class device that is converted into a Scsi_host.
@@ -1522,6 +1618,8 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
15221618
status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET);
15231619
else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0)
15241620
status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET);
1621+
else if (strncmp(buf, "trunk", sizeof("trunk") - 1) == 0)
1622+
status = lpfc_set_trunking(phba, (char *)buf + sizeof("trunk"));
15251623
else
15261624
status = -EINVAL;
15271625

@@ -6019,6 +6117,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
60196117
case LPFC_LINK_SPEED_64GHZ:
60206118
fc_host_speed(shost) = FC_PORTSPEED_64GBIT;
60216119
break;
6120+
case LPFC_LINK_SPEED_128GHZ:
6121+
fc_host_speed(shost) = FC_PORTSPEED_128GBIT;
6122+
break;
60226123
default:
60236124
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
60246125
break;

drivers/scsi/lpfc/lpfc_bsg.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5615,6 +5615,77 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
56155615
return rc;
56165616
}
56175617

5618+
static int
5619+
lpfc_get_trunk_info(struct bsg_job *job)
5620+
{
5621+
struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
5622+
struct lpfc_hba *phba = vport->phba;
5623+
struct fc_bsg_reply *bsg_reply = job->reply;
5624+
struct lpfc_trunk_info *event_reply;
5625+
int rc = 0;
5626+
5627+
if (job->request_len <
5628+
sizeof(struct fc_bsg_request) + sizeof(struct get_trunk_info_req)) {
5629+
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5630+
"2744 Received GET TRUNK _INFO request below "
5631+
"minimum size\n");
5632+
rc = -EINVAL;
5633+
goto job_error;
5634+
}
5635+
5636+
event_reply = (struct lpfc_trunk_info *)
5637+
bsg_reply->reply_data.vendor_reply.vendor_rsp;
5638+
5639+
if (job->reply_len <
5640+
sizeof(struct fc_bsg_request) + sizeof(struct lpfc_trunk_info)) {
5641+
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5642+
"2728 Received GET TRUNK _INFO reply below "
5643+
"minimum size\n");
5644+
rc = -EINVAL;
5645+
goto job_error;
5646+
}
5647+
if (event_reply == NULL) {
5648+
rc = -EINVAL;
5649+
goto job_error;
5650+
}
5651+
5652+
bsg_bf_set(lpfc_trunk_info_link_status, event_reply,
5653+
(phba->link_state >= LPFC_LINK_UP) ? 1 : 0);
5654+
5655+
bsg_bf_set(lpfc_trunk_info_trunk_active0, event_reply,
5656+
(phba->trunk_link.link0.state == LPFC_LINK_UP) ? 1 : 0);
5657+
5658+
bsg_bf_set(lpfc_trunk_info_trunk_active1, event_reply,
5659+
(phba->trunk_link.link1.state == LPFC_LINK_UP) ? 1 : 0);
5660+
5661+
bsg_bf_set(lpfc_trunk_info_trunk_active2, event_reply,
5662+
(phba->trunk_link.link2.state == LPFC_LINK_UP) ? 1 : 0);
5663+
5664+
bsg_bf_set(lpfc_trunk_info_trunk_active3, event_reply,
5665+
(phba->trunk_link.link3.state == LPFC_LINK_UP) ? 1 : 0);
5666+
5667+
bsg_bf_set(lpfc_trunk_info_trunk_config0, event_reply,
5668+
bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba));
5669+
5670+
bsg_bf_set(lpfc_trunk_info_trunk_config1, event_reply,
5671+
bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba));
5672+
5673+
bsg_bf_set(lpfc_trunk_info_trunk_config2, event_reply,
5674+
bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba));
5675+
5676+
bsg_bf_set(lpfc_trunk_info_trunk_config3, event_reply,
5677+
bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba));
5678+
5679+
event_reply->port_speed = phba->sli4_hba.link_state.speed / 1000;
5680+
event_reply->logical_speed =
5681+
phba->sli4_hba.link_state.logical_speed / 100;
5682+
job_error:
5683+
bsg_reply->result = rc;
5684+
bsg_job_done(job, bsg_reply->result,
5685+
bsg_reply->reply_payload_rcv_len);
5686+
return rc;
5687+
5688+
}
56185689

56195690
/**
56205691
* lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
@@ -5675,6 +5746,9 @@ lpfc_bsg_hst_vendor(struct bsg_job *job)
56755746
case LPFC_BSG_VENDOR_RAS_SET_CONFIG:
56765747
rc = lpfc_bsg_set_ras_config(job);
56775748
break;
5749+
case LPFC_BSG_VENDOR_GET_TRUNK_INFO:
5750+
rc = lpfc_get_trunk_info(job);
5751+
break;
56785752
default:
56795753
rc = -EINVAL;
56805754
bsg_reply->reply_payload_rcv_len = 0;

drivers/scsi/lpfc/lpfc_bsg.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define LPFC_BSG_VENDOR_RAS_GET_FWLOG 17
4343
#define LPFC_BSG_VENDOR_RAS_GET_CONFIG 18
4444
#define LPFC_BSG_VENDOR_RAS_SET_CONFIG 19
45+
#define LPFC_BSG_VENDOR_GET_TRUNK_INFO 20
4546

4647
struct set_ct_event {
4748
uint32_t command;
@@ -331,6 +332,43 @@ struct lpfc_bsg_get_ras_config_reply {
331332
uint32_t log_buff_sz;
332333
};
333334

335+
struct lpfc_trunk_info {
336+
uint32_t word0;
337+
#define lpfc_trunk_info_link_status_SHIFT 0
338+
#define lpfc_trunk_info_link_status_MASK 1
339+
#define lpfc_trunk_info_link_status_WORD word0
340+
#define lpfc_trunk_info_trunk_active0_SHIFT 8
341+
#define lpfc_trunk_info_trunk_active0_MASK 1
342+
#define lpfc_trunk_info_trunk_active0_WORD word0
343+
#define lpfc_trunk_info_trunk_active1_SHIFT 9
344+
#define lpfc_trunk_info_trunk_active1_MASK 1
345+
#define lpfc_trunk_info_trunk_active1_WORD word0
346+
#define lpfc_trunk_info_trunk_active2_SHIFT 10
347+
#define lpfc_trunk_info_trunk_active2_MASK 1
348+
#define lpfc_trunk_info_trunk_active2_WORD word0
349+
#define lpfc_trunk_info_trunk_active3_SHIFT 11
350+
#define lpfc_trunk_info_trunk_active3_MASK 1
351+
#define lpfc_trunk_info_trunk_active3_WORD word0
352+
#define lpfc_trunk_info_trunk_config0_SHIFT 12
353+
#define lpfc_trunk_info_trunk_config0_MASK 1
354+
#define lpfc_trunk_info_trunk_config0_WORD word0
355+
#define lpfc_trunk_info_trunk_config1_SHIFT 13
356+
#define lpfc_trunk_info_trunk_config1_MASK 1
357+
#define lpfc_trunk_info_trunk_config1_WORD word0
358+
#define lpfc_trunk_info_trunk_config2_SHIFT 14
359+
#define lpfc_trunk_info_trunk_config2_MASK 1
360+
#define lpfc_trunk_info_trunk_config2_WORD word0
361+
#define lpfc_trunk_info_trunk_config3_SHIFT 15
362+
#define lpfc_trunk_info_trunk_config3_MASK 1
363+
#define lpfc_trunk_info_trunk_config3_WORD word0
364+
uint16_t port_speed;
365+
uint16_t logical_speed;
366+
uint32_t reserved3;
367+
};
368+
369+
struct get_trunk_info_req {
370+
uint32_t command;
371+
};
334372

335373
/* driver only */
336374
#define SLI_CONFIG_NOT_HANDLED 0

drivers/scsi/lpfc/lpfc_ct.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,6 +2340,8 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
23402340

23412341
ae->un.AttrInt = 0;
23422342
if (!(phba->hba_flag & HBA_FCOE_MODE)) {
2343+
if (phba->lmt & LMT_128Gb)
2344+
ae->un.AttrInt |= HBA_PORTSPEED_128GFC;
23432345
if (phba->lmt & LMT_64Gb)
23442346
ae->un.AttrInt |= HBA_PORTSPEED_64GFC;
23452347
if (phba->lmt & LMT_32Gb)
@@ -2416,6 +2418,9 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
24162418
case LPFC_LINK_SPEED_64GHZ:
24172419
ae->un.AttrInt = HBA_PORTSPEED_64GFC;
24182420
break;
2421+
case LPFC_LINK_SPEED_128GHZ:
2422+
ae->un.AttrInt = HBA_PORTSPEED_128GFC;
2423+
break;
24192424
default:
24202425
ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
24212426
break;

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5377,6 +5377,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
53775377

53785378
desc->info.port_speed.speed = cpu_to_be16(rdp_speed);
53795379

5380+
if (phba->lmt & LMT_128Gb)
5381+
rdp_cap |= RDP_PS_128GB;
53805382
if (phba->lmt & LMT_64Gb)
53815383
rdp_cap |= RDP_PS_64GB;
53825384
if (phba->lmt & LMT_32Gb)

drivers/scsi/lpfc/lpfc_hbadisc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3114,6 +3114,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
31143114
case LPFC_LINK_SPEED_16GHZ:
31153115
case LPFC_LINK_SPEED_32GHZ:
31163116
case LPFC_LINK_SPEED_64GHZ:
3117+
case LPFC_LINK_SPEED_128GHZ:
31173118
break;
31183119
default:
31193120
phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN;

0 commit comments

Comments
 (0)