aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/rapidio/rio-scan.c59
-rw-r--r--drivers/rapidio/rio-sysfs.c4
-rw-r--r--include/linux/rio.h82
3 files changed, 75 insertions, 70 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 51f0af241eb7..45d14cd6b356 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -378,12 +378,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
378 struct rio_dev *rdev; 378 struct rio_dev *rdev;
379 struct rio_switch *rswitch = NULL; 379 struct rio_switch *rswitch = NULL;
380 int result, rdid; 380 int result, rdid;
381 size_t size;
382 u32 swpinfo = 0;
381 383
382 rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); 384 size = sizeof(struct rio_dev);
385 if (rio_mport_read_config_32(port, destid, hopcount,
386 RIO_PEF_CAR, &result))
387 return NULL;
388
389 if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) {
390 rio_mport_read_config_32(port, destid, hopcount,
391 RIO_SWP_INFO_CAR, &swpinfo);
392 if (result & RIO_PEF_SWITCH) {
393 size += (RIO_GET_TOTAL_PORTS(swpinfo) *
394 sizeof(rswitch->nextdev[0])) + sizeof(*rswitch);
395 }
396 }
397
398 rdev = kzalloc(size, GFP_KERNEL);
383 if (!rdev) 399 if (!rdev)
384 return NULL; 400 return NULL;
385 401
386 rdev->net = net; 402 rdev->net = net;
403 rdev->pef = result;
404 rdev->swpinfo = swpinfo;
387 rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, 405 rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR,
388 &result); 406 &result);
389 rdev->did = result >> 16; 407 rdev->did = result >> 16;
@@ -397,8 +415,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
397 rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, 415 rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR,
398 &result); 416 &result);
399 rdev->asm_rev = result >> 16; 417 rdev->asm_rev = result >> 16;
400 rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
401 &rdev->pef);
402 if (rdev->pef & RIO_PEF_EXT_FEATURES) { 418 if (rdev->pef & RIO_PEF_EXT_FEATURES) {
403 rdev->efptr = result & 0xffff; 419 rdev->efptr = result & 0xffff;
404 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, 420 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
@@ -408,11 +424,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
408 hopcount, RIO_EFB_ERR_MGMNT); 424 hopcount, RIO_EFB_ERR_MGMNT);
409 } 425 }
410 426
411 if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) {
412 rio_mport_read_config_32(port, destid, hopcount,
413 RIO_SWP_INFO_CAR, &rdev->swpinfo);
414 }
415
416 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, 427 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
417 &rdev->src_ops); 428 &rdev->src_ops);
418 rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, 429 rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
@@ -449,12 +460,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
449 460
450 /* If a PE has both switch and other functions, show it as a switch */ 461 /* If a PE has both switch and other functions, show it as a switch */
451 if (rio_is_switch(rdev)) { 462 if (rio_is_switch(rdev)) {
452 rswitch = kzalloc(sizeof(*rswitch) + 463 rswitch = rdev->rswitch;
453 RIO_GET_TOTAL_PORTS(rdev->swpinfo) *
454 sizeof(rswitch->nextdev[0]),
455 GFP_KERNEL);
456 if (!rswitch)
457 goto cleanup;
458 rswitch->switchid = next_switchid; 464 rswitch->switchid = next_switchid;
459 rswitch->port_ok = 0; 465 rswitch->port_ok = 0;
460 rswitch->route_table = kzalloc(sizeof(u8)* 466 rswitch->route_table = kzalloc(sizeof(u8)*
@@ -466,15 +472,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
466 for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); 472 for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
467 rdid++) 473 rdid++)
468 rswitch->route_table[rdid] = RIO_INVALID_ROUTE; 474 rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
469 rdev->rswitch = rswitch;
470 rswitch->rdev = rdev;
471 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 475 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
472 rdev->rswitch->switchid); 476 rswitch->switchid);
473 rio_switch_init(rdev, do_enum); 477 rio_switch_init(rdev, do_enum);
474 478
475 if (do_enum && rdev->rswitch->clr_table) 479 if (do_enum && rswitch->clr_table)
476 rdev->rswitch->clr_table(port, destid, hopcount, 480 rswitch->clr_table(port, destid, hopcount,
477 RIO_GLOBAL_TABLE); 481 RIO_GLOBAL_TABLE);
478 482
479 list_add_tail(&rswitch->node, &rio_switches); 483 list_add_tail(&rswitch->node, &rio_switches);
480 484
@@ -510,10 +514,9 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
510 return rdev; 514 return rdev;
511 515
512cleanup: 516cleanup:
513 if (rswitch) { 517 if (rswitch->route_table)
514 kfree(rswitch->route_table); 518 kfree(rswitch->route_table);
515 kfree(rswitch); 519
516 }
517 kfree(rdev); 520 kfree(rdev);
518 return NULL; 521 return NULL;
519} 522}
@@ -1072,7 +1075,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
1072 */ 1075 */
1073static void rio_update_route_tables(struct rio_mport *port) 1076static void rio_update_route_tables(struct rio_mport *port)
1074{ 1077{
1075 struct rio_dev *rdev; 1078 struct rio_dev *rdev, *swrdev;
1076 struct rio_switch *rswitch; 1079 struct rio_switch *rswitch;
1077 u8 sport; 1080 u8 sport;
1078 u16 destid; 1081 u16 destid;
@@ -1087,14 +1090,16 @@ static void rio_update_route_tables(struct rio_mport *port)
1087 continue; 1090 continue;
1088 1091
1089 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 1092 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
1093 swrdev = sw_to_rio_dev(rswitch);
1094
1090 /* Skip if destid ends in empty switch*/ 1095 /* Skip if destid ends in empty switch*/
1091 if (rswitch->rdev->destid == destid) 1096 if (swrdev->destid == destid)
1092 continue; 1097 continue;
1093 1098
1094 sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); 1099 sport = RIO_GET_PORT_NUM(swrdev->swpinfo);
1095 1100
1096 if (rswitch->add_entry) { 1101 if (rswitch->add_entry) {
1097 rio_route_add_entry(rswitch->rdev, 1102 rio_route_add_entry(swrdev,
1098 RIO_GLOBAL_TABLE, destid, 1103 RIO_GLOBAL_TABLE, destid,
1099 sport, 0); 1104 sport, 0);
1100 rswitch->route_table[destid] = sport; 1105 rswitch->route_table[destid] = sport;
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 137ed93ee33f..76b41853a877 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -217,7 +217,7 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev)
217 217
218 err = device_create_bin_file(&rdev->dev, &rio_config_attr); 218 err = device_create_bin_file(&rdev->dev, &rio_config_attr);
219 219
220 if (!err && rdev->rswitch) { 220 if (!err && (rdev->pef & RIO_PEF_SWITCH)) {
221 err = device_create_file(&rdev->dev, &dev_attr_routes); 221 err = device_create_file(&rdev->dev, &dev_attr_routes);
222 if (!err && rdev->rswitch->sw_sysfs) 222 if (!err && rdev->rswitch->sw_sysfs)
223 err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); 223 err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE);
@@ -239,7 +239,7 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev)
239void rio_remove_sysfs_dev_files(struct rio_dev *rdev) 239void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
240{ 240{
241 device_remove_bin_file(&rdev->dev, &rio_config_attr); 241 device_remove_bin_file(&rdev->dev, &rio_config_attr);
242 if (rdev->rswitch) { 242 if (rdev->pef & RIO_PEF_SWITCH) {
243 device_remove_file(&rdev->dev, &dev_attr_routes); 243 device_remove_file(&rdev->dev, &dev_attr_routes);
244 if (rdev->rswitch->sw_sysfs) 244 if (rdev->rswitch->sw_sysfs)
245 rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); 245 rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
diff --git a/include/linux/rio.h b/include/linux/rio.h
index f6e25b3a6967..9b558856a8b6 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -71,9 +71,47 @@ extern struct device rio_bus;
71extern struct list_head rio_devices; /* list of all devices */ 71extern struct list_head rio_devices; /* list of all devices */
72 72
73struct rio_mport; 73struct rio_mport;
74struct rio_dev;
74union rio_pw_msg; 75union rio_pw_msg;
75 76
76/** 77/**
78 * struct rio_switch - RIO switch info
79 * @node: Node in global list of switches
80 * @switchid: Switch ID that is unique across a network
81 * @route_table: Copy of switch routing table
82 * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0
83 * @add_entry: Callback for switch-specific route add function
84 * @get_entry: Callback for switch-specific route get function
85 * @clr_table: Callback for switch-specific clear route table function
86 * @set_domain: Callback for switch-specific domain setting function
87 * @get_domain: Callback for switch-specific domain get function
88 * @em_init: Callback for switch-specific error management init function
89 * @em_handle: Callback for switch-specific error management handler function
90 * @sw_sysfs: Callback that initializes switch-specific sysfs attributes
91 * @nextdev: Array of per-port pointers to the next attached device
92 */
93struct rio_switch {
94 struct list_head node;
95 u16 switchid;
96 u8 *route_table;
97 u32 port_ok;
98 int (*add_entry) (struct rio_mport *mport, u16 destid, u8 hopcount,
99 u16 table, u16 route_destid, u8 route_port);
100 int (*get_entry) (struct rio_mport *mport, u16 destid, u8 hopcount,
101 u16 table, u16 route_destid, u8 *route_port);
102 int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount,
103 u16 table);
104 int (*set_domain) (struct rio_mport *mport, u16 destid, u8 hopcount,
105 u8 sw_domain);
106 int (*get_domain) (struct rio_mport *mport, u16 destid, u8 hopcount,
107 u8 *sw_domain);
108 int (*em_init) (struct rio_dev *dev);
109 int (*em_handle) (struct rio_dev *dev, u8 swport);
110 int (*sw_sysfs) (struct rio_dev *dev, int create);
111 struct rio_dev *nextdev[0];
112};
113
114/**
77 * struct rio_dev - RIO device info 115 * struct rio_dev - RIO device info
78 * @global_list: Node in list of all RIO devices 116 * @global_list: Node in list of all RIO devices
79 * @net_list: Node in list of RIO devices in a network 117 * @net_list: Node in list of RIO devices in a network
@@ -93,7 +131,6 @@ union rio_pw_msg;
93 * @phys_efptr: RIO device extended features pointer 131 * @phys_efptr: RIO device extended features pointer
94 * @em_efptr: RIO Error Management features pointer 132 * @em_efptr: RIO Error Management features pointer
95 * @dma_mask: Mask of bits of RIO address this device implements 133 * @dma_mask: Mask of bits of RIO address this device implements
96 * @rswitch: Pointer to &struct rio_switch if valid for this device
97 * @driver: Driver claiming this device 134 * @driver: Driver claiming this device
98 * @dev: Device model device 135 * @dev: Device model device
99 * @riores: RIO resources this device owns 136 * @riores: RIO resources this device owns
@@ -101,6 +138,7 @@ union rio_pw_msg;
101 * @destid: Network destination ID (or associated destid for switch) 138 * @destid: Network destination ID (or associated destid for switch)
102 * @hopcount: Hopcount to this device 139 * @hopcount: Hopcount to this device
103 * @prev: Previous RIO device connected to the current one 140 * @prev: Previous RIO device connected to the current one
141 * @rswitch: struct rio_switch (if valid for this device)
104 */ 142 */
105struct rio_dev { 143struct rio_dev {
106 struct list_head global_list; /* node in list of all RIO devices */ 144 struct list_head global_list; /* node in list of all RIO devices */
@@ -121,7 +159,6 @@ struct rio_dev {
121 u32 phys_efptr; 159 u32 phys_efptr;
122 u32 em_efptr; 160 u32 em_efptr;
123 u64 dma_mask; 161 u64 dma_mask;
124 struct rio_switch *rswitch; /* RIO switch info */
125 struct rio_driver *driver; /* RIO driver claiming this device */ 162 struct rio_driver *driver; /* RIO driver claiming this device */
126 struct device dev; /* LDM device structure */ 163 struct device dev; /* LDM device structure */
127 struct resource riores[RIO_MAX_DEV_RESOURCES]; 164 struct resource riores[RIO_MAX_DEV_RESOURCES];
@@ -129,11 +166,13 @@ struct rio_dev {
129 u16 destid; 166 u16 destid;
130 u8 hopcount; 167 u8 hopcount;
131 struct rio_dev *prev; 168 struct rio_dev *prev;
169 struct rio_switch rswitch[0]; /* RIO switch info */
132}; 170};
133 171
134#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) 172#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list)
135#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list) 173#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list)
136#define to_rio_dev(n) container_of(n, struct rio_dev, dev) 174#define to_rio_dev(n) container_of(n, struct rio_dev, dev)
175#define sw_to_rio_dev(n) container_of(n, struct rio_dev, rswitch[0])
137 176
138/** 177/**
139 * struct rio_msg - RIO message event 178 * struct rio_msg - RIO message event
@@ -226,45 +265,6 @@ struct rio_net {
226#define RIO_SW_SYSFS_CREATE 1 /* Create switch attributes */ 265#define RIO_SW_SYSFS_CREATE 1 /* Create switch attributes */
227#define RIO_SW_SYSFS_REMOVE 0 /* Remove switch attributes */ 266#define RIO_SW_SYSFS_REMOVE 0 /* Remove switch attributes */
228 267
229/**
230 * struct rio_switch - RIO switch info
231 * @node: Node in global list of switches
232 * @rdev: Associated RIO device structure
233 * @switchid: Switch ID that is unique across a network
234 * @route_table: Copy of switch routing table
235 * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0
236 * @add_entry: Callback for switch-specific route add function
237 * @get_entry: Callback for switch-specific route get function
238 * @clr_table: Callback for switch-specific clear route table function
239 * @set_domain: Callback for switch-specific domain setting function
240 * @get_domain: Callback for switch-specific domain get function
241 * @em_init: Callback for switch-specific error management initialization function
242 * @em_handle: Callback for switch-specific error management handler function
243 * @sw_sysfs: Callback that initializes switch-specific sysfs attributes
244 * @nextdev: Array of per-port pointers to the next attached device
245 */
246struct rio_switch {
247 struct list_head node;
248 struct rio_dev *rdev;
249 u16 switchid;
250 u8 *route_table;
251 u32 port_ok;
252 int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
253 u16 table, u16 route_destid, u8 route_port);
254 int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
255 u16 table, u16 route_destid, u8 * route_port);
256 int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount,
257 u16 table);
258 int (*set_domain) (struct rio_mport *mport, u16 destid, u8 hopcount,
259 u8 sw_domain);
260 int (*get_domain) (struct rio_mport *mport, u16 destid, u8 hopcount,
261 u8 *sw_domain);
262 int (*em_init) (struct rio_dev *dev);
263 int (*em_handle) (struct rio_dev *dev, u8 swport);
264 int (*sw_sysfs) (struct rio_dev *dev, int create);
265 struct rio_dev *nextdev[0];
266};
267
268/* Low-level architecture-dependent routines */ 268/* Low-level architecture-dependent routines */
269 269
270/** 270/**